From 23d255c76e8dfc4af8504f3996862f69f6bf7650 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Fri, 22 Oct 2021 10:45:29 +0800 Subject: [PATCH 01/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0vm=20canvas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/js/default/common/canvas.js | 94 +- .../src/main/js/default/common/runtime/vm.js | 8618 +++++++++-------- 2 files changed, 4362 insertions(+), 4350 deletions(-) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index 2d429a6..0fe2e8f 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -25,72 +25,48 @@ export class OBCanvas2D { } this.canvas2dctx.fillStyle = str_color.substr(0,7); } + setStrokeStyleColor(color) { + let str_color; + if (color < 0) { + str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) + str_color = '#' + str_color; + } else { + str_color = '#' + color.toString(16).padStart(8, '0'); + } + this.canvas2dctx.fillStyle = str_color.substr(0,7); + } /** * 安装到脚本库 * @param {OBScript} script */ install(script) { - let self = this; script.InstallLib("canvas2d", "canvas2d", [ - self.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), // canvas2dctx.fillStyle=color - self.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), - self.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), - self.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), - self.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), - self.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), - self.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), ]); } - fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } } \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js index d7feb82..071aed0 100644 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ b/hap/entry/src/main/js/default/common/runtime/vm.js @@ -3,4294 +3,4330 @@ * Copyright 2021 Du Tian Wei * SPDX-License-Identifier: Apache-2.0 */ - import * as util from './util.js' - export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); - }); - }; - return f; - } - } - export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {integer} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } - } - export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int - } - export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; - } - export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } - } - export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; - } - export class OBCodeSegment { - name; - functions; - fsms; - } - export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - } - export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - } - export class OBMessageHandler { - Name; - Func; - ArgTypeName; - } - export class OBEventHandler { - Name; - Func; - } - export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } - } - export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - return new STMT_start(); - case 9: - return new B_STMT_end(); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } - } - export class PositionUpdatePair { - targetOffset; - callback; - } - export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - CurrentStatementStack = []; //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {OBStructValue} - */ - /** - * @type StructRegister[] - */ - StructRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {object} - */ - /** - * @type NObjectRegister[] - */ - NObjectRegister; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - } - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength / 4; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset == this.currentInstructPosition) { - p.callback(newPos); - } - }); - } - } - - export class OBBuildInFunctions { - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward == 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } - } - export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(); - registers.LongRegister = []; - registers.LongRegister.length = Def.IntegerCnt; - registers.DoubleRegister = []; - registers.DoubleRegister.length = Def.FloatCnt; - registers.StringRegister = []; - registers.StringRegister.length = Def.StringCnt; - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } - } - export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - if (type.startsWith("S") && type.endsWith(";")) { - type = type.substr(1, type.length - 2); - } - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - let def = this.StructDef[type]; - let group = this.Groups[type]; - let reader = group.Data; - let itemStart = 0; - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid == id) { - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - } - throw Error("找不到 ID为" + id + "的" + type); - } - } - - export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBubberReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } - } - class Relocation { - /** - * @type {Object.} - */ - string = {}; - /** - * @type {Object.} - */ - integer = {}; - /** - * @type {Object.} - */ - float = {}; - /** - * @type {Object.} - */ - bin = {}; - /** - * @type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } - } - export class OBStructDataSerializer { - relocation = new Relocation(); - /** - * - * @param {OBStructValue[]} valueData - * @returns {int[]} - */ - serialize(valueDataArray) { - let group = this.groupData(valueDataArray); - } - /** - * - * @param {OBStructValue[]} valueDataArray - * @returns {Object. { - let list = group[d.Def.Name]; - if (!list) { - list = []; - group[d.Def.Name] = list; - } - this.collData(d); - list.push(d); - }); - return group; - } - /** - * - * @param {OBStructValue} d - */ - collData(d) { - d.string.forEach(str => { - this.relocation.addRelocationString(str); - }); - d.registers.object.forEach(ofd => { - switch (ofd.type.$__type) { - case "StructFieldTypeStruct": - break; - case "StructFieldTypeIntegerMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - case "StructFieldTypeStringMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - break; - case "StructFieldTypeList": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - default: - console.error(ofd); - throw Error("功能未实现 " + ofd.type.$__type); - } - }); - } - } - export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw new FileLoadException("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName == s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - let typeIdx = reader.ReadInt32(); - let count = reader.ReadInt32(); - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadInt32(); - let d = {}; - let cnt = reader.ReadInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } - } - - export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos, true); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(start, true); - if (length == 0) { - return ""; - } - let ab = this.buf.slice(start + 4, start + 4 + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - let str = utf8decoder.decode(ui8); - if (str == null) { - throw Error('no string value of idx:' + stringIdx); - } - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - let buf; - if (typeof (length) == "undefined") { - buf = this.buf.slice(pos); - } else { - buf = this.buf.slice(pos, pos + length); - } - return new OBArrayBufferReader(buf); - } - - seek(pos) { - if (typeof (pos) == "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } - } - - - export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - this.Actions.push(Instruction); - } - } - // 虚拟机 - - export class VMInterruptException { - } - export class ChangeStateException extends VMInterruptException { - } - export class ChangeDestroyException extends VMInterruptException { - } - export class OBVM { - /** - * @type {function(any)} - */ - Output; - /** - * typeName->[VMFSM] - * @type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f == fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {OBVMAction} callback - */ - Schedule(millisecond, callback) { - setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } - } - export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.Fsmdata.Name); - } - } - } - export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.LongRegister = []; - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.DoubleRegister = []; - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.StringRegister = []; - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.StructRegister = []; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.NObjectRegister = []; - break; - default: - throw Error("Unknown type " + v.TypeIdx); - } - }); - } - } - export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {TypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let h = this.data.EventHandlers[msg.name]; - if (h) { - this.currentMessage = msg; - new OBVMFunction(h.Func).Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let hl = this.data.MessageHandlers[m.name]; - if (hl) { - hl.forEach(h => { - if (h.ArgTypeName == "" || h.ArgTypeName == typeName) { - new OBVMFunction(h.Func).Call(this); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } - } - export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {TypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - LocalVar.LongRegister = []; - LocalVar.DoubleRegister = []; - LocalVar.StringRegister = []; - LocalVar.StructRegister = []; - LocalVar.NObjectRegister = []; - for (let i = 0; i < obfunc.StringLocalVariableCount; i++) { - LocalVar.StringRegister[i] = ""; - } - } - /** - * - * @param {OBVMState} state - */ - Call(state) { - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType == 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType == 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType == 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType == 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType == 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } - } - export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return "Struct"; - case 4: - // return "NObject"; - if (arg.constructor == OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } - } - export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - // 字节码 - export class STMT_start extends OBInstruction { - StatementContext; - - init(code, builder, instructions, i) { - this.StatementContext = new OBStatementContext(); - this.StatementContext.InstPos = this.Position; - } - - link(builder, instructions, i) { - if (builder.CurrentStatementStack.length > 0) { - let Actions = null; - builder.PushAction((st, uf, locals, pos) => { - if (Actions == null) { - Actions = this.StatementContext.Actions; - } - for (let i = 0; i < Actions.length;) { - let action = Actions[i]; - i = action(st, uf, locals, i); - } - return pos + 1; - }); - } - builder.CurrentStatementStack.push(this.StatementContext); - } - } - export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFFF000) >> 12; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } - } - export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } - } - export class B_STMT_end extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - let sc = builder.CurrentStatementStack.pop(); - if (builder.CurrentStatementStack.length == 0) { - builder.RootStatementContext = sc; - } - } - } - export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } - } - export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } - } - export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } - } - export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } - } - export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } - } - export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } - } - export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister == -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } - } - export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) == 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) == 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" == (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } - } - export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } - } - export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } - } - export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } - } - - export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } - } - export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFFF000) >> 12); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFF; - switch (specal) { - case 0xFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFFF000) >> 12); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } - } - export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } - return fsm; - }; - } - } - export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } - } - - export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" == (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } - } - export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - let enable = true; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - if (enable) { - enable = false; - let v = LongReg(st, uf, locals); - return v - 1; - } else { - throw Error("reentry"); - } - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - if (enable) { - enable = false; - let v = DoubleReg(st, uf, locals); - return v - 1; - } else { - throw Error("reentry"); - } - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } - } - export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } - } - export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) == RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - - export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } - } - export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body), st.fsm); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - - /** - * 单元数操作 - */ - export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } - } - export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } - } - export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } - } - export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - } - export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body), FSM); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } - } - export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } - } - export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } - } - export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } - } - export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } - } - export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } - } - /** - * value of may by key - */ - export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return !!c; - } else { - return 0; - } - }; - } - } - export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return !!c; - } - }; - } - } - export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return !v; - }; - } - } - export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } - } \ No newline at end of file +import * as util from './util.js' +export class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + func.apply(null, argVals); + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + return func.apply(null, argVals); + }); + }; + return f; + } +} +export class OBScript { + NativeLibHash = {}; // libname->hash + InstalledLibs = {}; + NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + StructDef = {}; // typename-> def + loadedFunctions; //= {};//function sign->function + FullNameFSMData = {}; //FullName->OBFSM + + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } +} +export class OBStructDef { + Name; //string + StructCnt; // int + StringCnt; // int + IntegerCnt; // int + FloatCnt; // int + NobjectCnt; // int + StructFields; // int +} +export class OBStructValueData { + /** + * @type {OBArrayBufferReader} + */ + Data; //arraybuffer + FullName; + Offset; + Length; + StructCount; +} +export class OBVariableInfo { + typeIdx; + count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } +} +export class OBState { + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + Name; + MessageHandlers; + EventHandlers; +} +export class OBCodeSegment { + name; + functions; + fsms; +} +export class OBFunction { + /** + * @type {OBVariableInfo[]} + */ + Variables; + instructions; + /** + * @type {String} + */ + Signure; + Statements; +} +export class OBFSM { + /** + * @type {string} + */ + Name; + /** + * @type {Object.} + */ + States; //string->state + /** + * @type {OBState} + */ + Entry; //state + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + FullName; + /** + * @type {string} + */ + ModuleName; +} +export class OBMessageHandler { + Name; + Func; + ArgTypeName; +} +export class OBEventHandler { + Name; + Func; +} +export class OBInstruction { + Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } +} +export class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + return new STMT_start(); + case 9: + return new B_STMT_end(); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } +} +export class PositionUpdatePair { + targetOffset; + callback; +} +export class OBFunctionBuilder { + loader; //OBScriptLoader + StatementLength; //integer + BuildingFunc; //OBFunction + PositionUpdatePairList; + currentInstructPosition; //integer + CurrentStatementStack = []; //[StatementContext] + + /** + * @callback LongRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type LongRegister[] + */ + LongRegister; + /** + * @callback DoubleRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type DoubleRegister[] + */ + DoubleRegister; + /** + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {string} + */ + /** + * @type StringRegister[] + */ + StringRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {OBStructValue} + */ + /** + * @type {Array} StructRegister[] + */ + StructRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {object} + */ + /** + * @type {Array} NObjectRegister[] + */ + NObjectRegister; + + constructor(loader) { + this.loader = loader; + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength / 4; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } +} + +export class OBBuildInFunctions{ + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } +}; +export class OBStructValue { + /** + * @type {OBStructDef} + */ + Def; + /** + * @type {OBTypedVariableGroup} + */ + registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } +} +export class StructData { + /** + * @type {Object.} + */ + StructDef; + /** + * @type {Object.} + */ + Groups; + /** + * @type {OBArrayBufferReader} + */ + DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } +} + +export class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } +} +class Relocation { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + string = {}; + /** + * @1type {Object.} + */ + integer = {}; + /** + * @1type {Object.} + */ + float = {}; + /** + * @1type {Object.} + */ + bin = {}; + /** + * @1type {Object.} + */ + structFieldIndex = {}; + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } +} +export class OBScriptLoader { + /** + * @type {OBArrayBufferReader} + */ + reader; //OBArrayBufferReader + /** + * @type {OBArrayBufferReader} + */ + data; //OBArrayBufferReader + loadingFunctions = {}; //[OBFunctionBuilder] + Linkings = []; //Linkable + + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + let typeIdx = reader.ReadInt32(); + let count = reader.ReadInt32(); + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadInt32(); + let d = {}; + let cnt = reader.ReadInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } +} + +export class OBArrayBufferReader { + /** + * @type {Number} integer of position + */ + pos; // int + /** + * @type {ArrayBuffer} + */ + buf; // ArrayBuffer + /** + * @type DataView + */ + view; // DataView + /** + * @type {Object.} + */ + stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.view = new DataView(buf); + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(start, true); + if (length === 0) { + return ""; + } + let ab = this.buf.slice(start + 4, start + 4 + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + let str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + let buf; + if (typeof (length) === "undefined") { + buf = this.buf.slice(pos); + } else { + buf = this.buf.slice(pos, pos + length); + } + return new OBArrayBufferReader(buf); + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } +} + + +export class OBStatementContext { + InstPos; + Actions = []; + + PushAction(Instruction) { + this.Actions.push(Instruction); + } +} +// 虚拟机 + +export class VMInterruptException { +} +export class ChangeStateException extends VMInterruptException { +} +export class ChangeDestroyException extends VMInterruptException { +} +export class OBVM { + /** + * @1type {function(any)} + */ + Output; + /** + * typeName->[VMFSM] + * @1type {Object.} + */ + Running = {}; + /** + * @type OBScript + */ + script; + /** + * @1type {OBVMFSM} + */ + Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script) { + if (!script) { + throw Error("Script is null"); + } + this.script = script; + } + + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } +} +export class OBVMFSM { + static ID_GEN = 0; + /** + * @type {any} + */ + Target; + /** + * @type {OBFSM} + */ + data; + id; + /** + * @type {OBVMState} + */ + CurrentState; + /** + * @type {OBVMState[]} + */ + StateStack = []; + /** + * @type {OBVM} + */ + VM; + Inbox = []; + PrioritizedInbox = []; + VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.data = data; + this.id = ++OBVMFSM.ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null,null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } +} +export class OBTypedVariableGroup { + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } +} +export class OBVMState { + /** + * @type {OBState} + */ + data; + /** + * @type {OBVMFSM} + */ + fsm; + /** + * @type {OBTypedVariableGroup} + */ + VariableGroup; + /** + * @type {OBMessage} + */ + currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } +} +export class OBVMFunction { + /** + * @type {OBFunction} + */ + data; + /** + * @type {OBTypedVariableGroup} + */ + LocalVar; + returnType = -1; + returnValue; + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } +} +export class OBMessage { + name; + arg; + argType; + sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } +} +export class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } +} +export class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } +} +// 字节码 +export class STMT_start extends OBInstruction { + StatementContext; + + init(code, builder, instructions, i) { + this.StatementContext = new OBStatementContext(); + this.StatementContext.InstPos = this.Position; + } + + link(builder, instructions, i) { + if (builder.CurrentStatementStack.length > 0) { + let Actions = null; + builder.PushAction((st, uf, locals, pos) => { + if (Actions == null) { + Actions = this.StatementContext.Actions; + } + for (let i = 0; i < Actions.length;) { + let action = Actions[i]; + i = action(st, uf, locals, i); + } + return pos + 1; + }); + } + builder.CurrentStatementStack.push(this.StatementContext); + } +} +export class LDSTR extends OBInstruction { + Value; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFFF000) >> 12; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } +} +export class PRT extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } +} +export class B_STMT_end extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + let sc = builder.CurrentStatementStack.pop(); + if (builder.CurrentStatementStack.length === 0) { + builder.RootStatementContext = sc; + } + } +} +export class ReceivedMessage extends OBInstruction { + typeId; + Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } +} +export class STVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } +} +export class STVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } +} +export class StructFieldDesc extends OBInstruction { + fieldTypeId; + fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } +} +export class GetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + return stt.registers.LongRegister[fieldIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } +} +export class SetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } +} +export class CHSTT extends OBInstruction { + StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } +} +export class MethodCallRegisterInfoAnchor extends OBInstruction { + RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } +} +export class NativeMethodCall extends OBInstruction { + LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } +} +export class FSMVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } +} +export class SLF extends OBInstruction { + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } +} +export class MethodCall extends OBInstruction { + MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } +} +export class BRIFN extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } +} +export class BR extends OBInstruction { + Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } +} +export class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } +} +export class ARITHF extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } +} + +export class ARITHI extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } +} +export class LDI extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFFF000) >> 12); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } +} +export class LDF extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFF; + switch (specal) { + case 0xFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFFF000) >> 12); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } +} +export class RET extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } +} +export class FSMVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } +} +export class CreateFSM extends OBInstruction { + FSMTypeName; + ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } +} +export class FSMSendMsg extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} +export class GZ0 extends OBInstruction { + VarType; + VarIdx; + ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } +} + +export class BRIF extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } +} +export class DEC extends OBInstruction { + regType; + regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + let enable = true; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + if (enable) { + enable = false; + let v = LongReg(st, uf, locals); + return v - 1; + } else { + throw Error("reentry"); + } + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + if (enable) { + enable = false; + let v = DoubleReg(st, uf, locals); + return v - 1; + } else { + throw Error("reentry"); + } + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } +} +export class Reg2Var extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } +} +export class Var2Reg extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } +} +export class I2F extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } +} +export class EQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class NEQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class LT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class LTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class GT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } +} + +export class GTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } +} +export class FSMBroadcastMsg extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} + +/** + * 单元数操作 + */ +export class SGLF extends OBInstruction { + Opcode; + value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } +} +export class RAND extends OBInstruction { + Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } +} +export class F2I extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } +} +export class FSMSendMsgWait_Data extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } +} +export class FSMSendMsgWait extends OBInstruction { + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } +} +export class FSMBroadcastMsgWait extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} +export class TextJoin extends OBInstruction { + Left; + Right; + RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } +} +export class ToString extends OBInstruction { + ValueType; + ValueRegIdx; + RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } +} +export class Sender extends OBInstruction { + RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } +} +export class SHL extends OBInstruction { + value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } +} +export class AND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } +} +export class FIX extends OBInstruction { + regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } +} +/** + * value of may by key + */ +export class VOM extends OBInstruction { + map; + key; + ValueType; + RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } +} +export class LAND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } +} +export class LOR extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 0 : 1; + } + }; + } +} +export class LNOT extends OBInstruction { + a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } +} +export class COND extends OBInstruction { + if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } +} +export class NEW extends OBInstruction { + StructDef; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFFF000) >> 12; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } +} \ No newline at end of file -- Gitee From 092c6dccafebbef5bfdbf788e764a9f4f8cbcb0b Mon Sep 17 00:00:00 2001 From: duzc2 Date: Fri, 22 Oct 2021 10:45:29 +0800 Subject: [PATCH 02/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0vm=20canvas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- .../src/main/js/default/common/canvas.js | 94 +- .../src/main/js/default/common/runtime/vm.js | 8618 +++++++++-------- 2 files changed, 4362 insertions(+), 4350 deletions(-) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index 2d429a6..0fe2e8f 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -25,72 +25,48 @@ export class OBCanvas2D { } this.canvas2dctx.fillStyle = str_color.substr(0,7); } + setStrokeStyleColor(color) { + let str_color; + if (color < 0) { + str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) + str_color = '#' + str_color; + } else { + str_color = '#' + color.toString(16).padStart(8, '0'); + } + this.canvas2dctx.fillStyle = str_color.substr(0,7); + } /** * 安装到脚本库 * @param {OBScript} script */ install(script) { - let self = this; script.InstallLib("canvas2d", "canvas2d", [ - self.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), // canvas2dctx.fillStyle=color - self.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), - self.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), - self.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister']), - self.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), - self.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), - self.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), - self.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), ]); } - fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } } \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js index d7feb82..071aed0 100644 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ b/hap/entry/src/main/js/default/common/runtime/vm.js @@ -3,4294 +3,4330 @@ * Copyright 2021 Du Tian Wei * SPDX-License-Identifier: Apache-2.0 */ - import * as util from './util.js' - export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); - }); - }; - return f; - } - } - export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {integer} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } - } - export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int - } - export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; - } - export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } - } - export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; - } - export class OBCodeSegment { - name; - functions; - fsms; - } - export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - } - export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - } - export class OBMessageHandler { - Name; - Func; - ArgTypeName; - } - export class OBEventHandler { - Name; - Func; - } - export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } - } - export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - return new STMT_start(); - case 9: - return new B_STMT_end(); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } - } - export class PositionUpdatePair { - targetOffset; - callback; - } - export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - CurrentStatementStack = []; //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {OBStructValue} - */ - /** - * @type StructRegister[] - */ - StructRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @param {number} - * @returns {object} - */ - /** - * @type NObjectRegister[] - */ - NObjectRegister; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - } - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength / 4; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset == this.currentInstructPosition) { - p.callback(newPos); - } - }); - } - } - - export class OBBuildInFunctions { - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward == 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } - } - export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(); - registers.LongRegister = []; - registers.LongRegister.length = Def.IntegerCnt; - registers.DoubleRegister = []; - registers.DoubleRegister.length = Def.FloatCnt; - registers.StringRegister = []; - registers.StringRegister.length = Def.StringCnt; - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } - } - export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - if (type.startsWith("S") && type.endsWith(";")) { - type = type.substr(1, type.length - 2); - } - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - let def = this.StructDef[type]; - let group = this.Groups[type]; - let reader = group.Data; - let itemStart = 0; - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid == id) { - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - } - throw Error("找不到 ID为" + id + "的" + type); - } - } - - export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBubberReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } - } - class Relocation { - /** - * @type {Object.} - */ - string = {}; - /** - * @type {Object.} - */ - integer = {}; - /** - * @type {Object.} - */ - float = {}; - /** - * @type {Object.} - */ - bin = {}; - /** - * @type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } - } - export class OBStructDataSerializer { - relocation = new Relocation(); - /** - * - * @param {OBStructValue[]} valueData - * @returns {int[]} - */ - serialize(valueDataArray) { - let group = this.groupData(valueDataArray); - } - /** - * - * @param {OBStructValue[]} valueDataArray - * @returns {Object. { - let list = group[d.Def.Name]; - if (!list) { - list = []; - group[d.Def.Name] = list; - } - this.collData(d); - list.push(d); - }); - return group; - } - /** - * - * @param {OBStructValue} d - */ - collData(d) { - d.string.forEach(str => { - this.relocation.addRelocationString(str); - }); - d.registers.object.forEach(ofd => { - switch (ofd.type.$__type) { - case "StructFieldTypeStruct": - break; - case "StructFieldTypeIntegerMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - case "StructFieldTypeStringMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - break; - case "StructFieldTypeList": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - default: - console.error(ofd); - throw Error("功能未实现 " + ofd.type.$__type); - } - }); - } - } - export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw new FileLoadException("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName == s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - let typeIdx = reader.ReadInt32(); - let count = reader.ReadInt32(); - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadInt32(); - let d = {}; - let cnt = reader.ReadInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } - } - - export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos, true); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(start, true); - if (length == 0) { - return ""; - } - let ab = this.buf.slice(start + 4, start + 4 + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - let str = utf8decoder.decode(ui8); - if (str == null) { - throw Error('no string value of idx:' + stringIdx); - } - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - let buf; - if (typeof (length) == "undefined") { - buf = this.buf.slice(pos); - } else { - buf = this.buf.slice(pos, pos + length); - } - return new OBArrayBufferReader(buf); - } - - seek(pos) { - if (typeof (pos) == "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } - } - - - export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - this.Actions.push(Instruction); - } - } - // 虚拟机 - - export class VMInterruptException { - } - export class ChangeStateException extends VMInterruptException { - } - export class ChangeDestroyException extends VMInterruptException { - } - export class OBVM { - /** - * @type {function(any)} - */ - Output; - /** - * typeName->[VMFSM] - * @type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f == fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {OBVMAction} callback - */ - Schedule(millisecond, callback) { - setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } - } - export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.Fsmdata.Name); - } - } - } - export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.LongRegister = []; - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.DoubleRegister = []; - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.StringRegister = []; - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.StructRegister = []; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.TypeIdx); - } - this.NObjectRegister = []; - break; - default: - throw Error("Unknown type " + v.TypeIdx); - } - }); - } - } - export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {TypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let h = this.data.EventHandlers[msg.name]; - if (h) { - this.currentMessage = msg; - new OBVMFunction(h.Func).Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let hl = this.data.MessageHandlers[m.name]; - if (hl) { - hl.forEach(h => { - if (h.ArgTypeName == "" || h.ArgTypeName == typeName) { - new OBVMFunction(h.Func).Call(this); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } - } - export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {TypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - LocalVar.LongRegister = []; - LocalVar.DoubleRegister = []; - LocalVar.StringRegister = []; - LocalVar.StructRegister = []; - LocalVar.NObjectRegister = []; - for (let i = 0; i < obfunc.StringLocalVariableCount; i++) { - LocalVar.StringRegister[i] = ""; - } - } - /** - * - * @param {OBVMState} state - */ - Call(state) { - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType == 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType == 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType == 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType == 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType == 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } - } - export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return "Struct"; - case 4: - // return "NObject"; - if (arg.constructor == OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } - } - export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - // 字节码 - export class STMT_start extends OBInstruction { - StatementContext; - - init(code, builder, instructions, i) { - this.StatementContext = new OBStatementContext(); - this.StatementContext.InstPos = this.Position; - } - - link(builder, instructions, i) { - if (builder.CurrentStatementStack.length > 0) { - let Actions = null; - builder.PushAction((st, uf, locals, pos) => { - if (Actions == null) { - Actions = this.StatementContext.Actions; - } - for (let i = 0; i < Actions.length;) { - let action = Actions[i]; - i = action(st, uf, locals, i); - } - return pos + 1; - }); - } - builder.CurrentStatementStack.push(this.StatementContext); - } - } - export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFFF000) >> 12; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } - } - export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } - } - export class B_STMT_end extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - let sc = builder.CurrentStatementStack.pop(); - if (builder.CurrentStatementStack.length == 0) { - builder.RootStatementContext = sc; - } - } - } - export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } - } - export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } - } - export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } - } - export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } - } - export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } - } - export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } - } - export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister == -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } - } - export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) == 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) == 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" == (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } - } - export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } - } - export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } - } - export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } - } - - export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } - } - export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFFF000) >> 12); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFF; - switch (specal) { - case 0xFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFFF000) >> 12); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } - } - export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } - return fsm; - }; - } - } - export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } - } - - export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" == (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } - } - export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - let enable = true; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - if (enable) { - enable = false; - let v = LongReg(st, uf, locals); - return v - 1; - } else { - throw Error("reentry"); - } - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - if (enable) { - enable = false; - let v = DoubleReg(st, uf, locals); - return v - 1; - } else { - throw Error("reentry"); - } - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } - } - export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } - } - export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) == RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - - export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } - } - export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body), st.fsm); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - - /** - * 单元数操作 - */ - export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } - } - export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } - } - export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } - } - export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - } - export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body), FSM); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } - } - export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } - } - export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } - } - export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } - } - export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } - } - export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } - } - /** - * value of may by key - */ - export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return !!c; - } else { - return 0; - } - }; - } - } - export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return !!c; - } - }; - } - } - export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return !v; - }; - } - } - export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } - } \ No newline at end of file +import * as util from './util.js' +export class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + func.apply(null, argVals); + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + return func.apply(null, argVals); + }); + }; + return f; + } +} +export class OBScript { + NativeLibHash = {}; // libname->hash + InstalledLibs = {}; + NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + StructDef = {}; // typename-> def + loadedFunctions; //= {};//function sign->function + FullNameFSMData = {}; //FullName->OBFSM + + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } +} +export class OBStructDef { + Name; //string + StructCnt; // int + StringCnt; // int + IntegerCnt; // int + FloatCnt; // int + NobjectCnt; // int + StructFields; // int +} +export class OBStructValueData { + /** + * @type {OBArrayBufferReader} + */ + Data; //arraybuffer + FullName; + Offset; + Length; + StructCount; +} +export class OBVariableInfo { + typeIdx; + count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } +} +export class OBState { + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + Name; + MessageHandlers; + EventHandlers; +} +export class OBCodeSegment { + name; + functions; + fsms; +} +export class OBFunction { + /** + * @type {OBVariableInfo[]} + */ + Variables; + instructions; + /** + * @type {String} + */ + Signure; + Statements; +} +export class OBFSM { + /** + * @type {string} + */ + Name; + /** + * @type {Object.} + */ + States; //string->state + /** + * @type {OBState} + */ + Entry; //state + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + FullName; + /** + * @type {string} + */ + ModuleName; +} +export class OBMessageHandler { + Name; + Func; + ArgTypeName; +} +export class OBEventHandler { + Name; + Func; +} +export class OBInstruction { + Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } +} +export class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + return new STMT_start(); + case 9: + return new B_STMT_end(); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } +} +export class PositionUpdatePair { + targetOffset; + callback; +} +export class OBFunctionBuilder { + loader; //OBScriptLoader + StatementLength; //integer + BuildingFunc; //OBFunction + PositionUpdatePairList; + currentInstructPosition; //integer + CurrentStatementStack = []; //[StatementContext] + + /** + * @callback LongRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type LongRegister[] + */ + LongRegister; + /** + * @callback DoubleRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type DoubleRegister[] + */ + DoubleRegister; + /** + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {string} + */ + /** + * @type StringRegister[] + */ + StringRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {OBStructValue} + */ + /** + * @type {Array} StructRegister[] + */ + StructRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {object} + */ + /** + * @type {Array} NObjectRegister[] + */ + NObjectRegister; + + constructor(loader) { + this.loader = loader; + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength / 4; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } +} + +export class OBBuildInFunctions{ + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } +}; +export class OBStructValue { + /** + * @type {OBStructDef} + */ + Def; + /** + * @type {OBTypedVariableGroup} + */ + registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } +} +export class StructData { + /** + * @type {Object.} + */ + StructDef; + /** + * @type {Object.} + */ + Groups; + /** + * @type {OBArrayBufferReader} + */ + DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } +} + +export class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } +} +class Relocation { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + string = {}; + /** + * @1type {Object.} + */ + integer = {}; + /** + * @1type {Object.} + */ + float = {}; + /** + * @1type {Object.} + */ + bin = {}; + /** + * @1type {Object.} + */ + structFieldIndex = {}; + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } +} +export class OBScriptLoader { + /** + * @type {OBArrayBufferReader} + */ + reader; //OBArrayBufferReader + /** + * @type {OBArrayBufferReader} + */ + data; //OBArrayBufferReader + loadingFunctions = {}; //[OBFunctionBuilder] + Linkings = []; //Linkable + + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + let typeIdx = reader.ReadInt32(); + let count = reader.ReadInt32(); + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadInt32(); + let d = {}; + let cnt = reader.ReadInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } +} + +export class OBArrayBufferReader { + /** + * @type {Number} integer of position + */ + pos; // int + /** + * @type {ArrayBuffer} + */ + buf; // ArrayBuffer + /** + * @type DataView + */ + view; // DataView + /** + * @type {Object.} + */ + stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.view = new DataView(buf); + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(start, true); + if (length === 0) { + return ""; + } + let ab = this.buf.slice(start + 4, start + 4 + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + let str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + let buf; + if (typeof (length) === "undefined") { + buf = this.buf.slice(pos); + } else { + buf = this.buf.slice(pos, pos + length); + } + return new OBArrayBufferReader(buf); + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } +} + + +export class OBStatementContext { + InstPos; + Actions = []; + + PushAction(Instruction) { + this.Actions.push(Instruction); + } +} +// 虚拟机 + +export class VMInterruptException { +} +export class ChangeStateException extends VMInterruptException { +} +export class ChangeDestroyException extends VMInterruptException { +} +export class OBVM { + /** + * @1type {function(any)} + */ + Output; + /** + * typeName->[VMFSM] + * @1type {Object.} + */ + Running = {}; + /** + * @type OBScript + */ + script; + /** + * @1type {OBVMFSM} + */ + Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script) { + if (!script) { + throw Error("Script is null"); + } + this.script = script; + } + + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } +} +export class OBVMFSM { + static ID_GEN = 0; + /** + * @type {any} + */ + Target; + /** + * @type {OBFSM} + */ + data; + id; + /** + * @type {OBVMState} + */ + CurrentState; + /** + * @type {OBVMState[]} + */ + StateStack = []; + /** + * @type {OBVM} + */ + VM; + Inbox = []; + PrioritizedInbox = []; + VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.data = data; + this.id = ++OBVMFSM.ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null,null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } +} +export class OBTypedVariableGroup { + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } +} +export class OBVMState { + /** + * @type {OBState} + */ + data; + /** + * @type {OBVMFSM} + */ + fsm; + /** + * @type {OBTypedVariableGroup} + */ + VariableGroup; + /** + * @type {OBMessage} + */ + currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } +} +export class OBVMFunction { + /** + * @type {OBFunction} + */ + data; + /** + * @type {OBTypedVariableGroup} + */ + LocalVar; + returnType = -1; + returnValue; + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } +} +export class OBMessage { + name; + arg; + argType; + sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } +} +export class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } +} +export class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } +} +// 字节码 +export class STMT_start extends OBInstruction { + StatementContext; + + init(code, builder, instructions, i) { + this.StatementContext = new OBStatementContext(); + this.StatementContext.InstPos = this.Position; + } + + link(builder, instructions, i) { + if (builder.CurrentStatementStack.length > 0) { + let Actions = null; + builder.PushAction((st, uf, locals, pos) => { + if (Actions == null) { + Actions = this.StatementContext.Actions; + } + for (let i = 0; i < Actions.length;) { + let action = Actions[i]; + i = action(st, uf, locals, i); + } + return pos + 1; + }); + } + builder.CurrentStatementStack.push(this.StatementContext); + } +} +export class LDSTR extends OBInstruction { + Value; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFFF000) >> 12; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } +} +export class PRT extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } +} +export class B_STMT_end extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + let sc = builder.CurrentStatementStack.pop(); + if (builder.CurrentStatementStack.length === 0) { + builder.RootStatementContext = sc; + } + } +} +export class ReceivedMessage extends OBInstruction { + typeId; + Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } +} +export class STVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } +} +export class STVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } +} +export class StructFieldDesc extends OBInstruction { + fieldTypeId; + fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } +} +export class GetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + return stt.registers.LongRegister[fieldIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } +} +export class SetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } +} +export class CHSTT extends OBInstruction { + StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } +} +export class MethodCallRegisterInfoAnchor extends OBInstruction { + RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } +} +export class NativeMethodCall extends OBInstruction { + LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } +} +export class FSMVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } +} +export class SLF extends OBInstruction { + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } +} +export class MethodCall extends OBInstruction { + MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } +} +export class BRIFN extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } +} +export class BR extends OBInstruction { + Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } +} +export class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } +} +export class ARITHF extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } +} + +export class ARITHI extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } +} +export class LDI extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFFF000) >> 12); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } +} +export class LDF extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFF; + switch (specal) { + case 0xFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFFF000) >> 12); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } +} +export class RET extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } +} +export class FSMVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } +} +export class CreateFSM extends OBInstruction { + FSMTypeName; + ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } +} +export class FSMSendMsg extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} +export class GZ0 extends OBInstruction { + VarType; + VarIdx; + ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } +} + +export class BRIF extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } +} +export class DEC extends OBInstruction { + regType; + regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + let enable = true; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + if (enable) { + enable = false; + let v = LongReg(st, uf, locals); + return v - 1; + } else { + throw Error("reentry"); + } + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + if (enable) { + enable = false; + let v = DoubleReg(st, uf, locals); + return v - 1; + } else { + throw Error("reentry"); + } + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } +} +export class Reg2Var extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } +} +export class Var2Reg extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } +} +export class I2F extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } +} +export class EQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class NEQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class LT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class LTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class GT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } +} + +export class GTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } +} +export class FSMBroadcastMsg extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} + +/** + * 单元数操作 + */ +export class SGLF extends OBInstruction { + Opcode; + value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } +} +export class RAND extends OBInstruction { + Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } +} +export class F2I extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } +} +export class FSMSendMsgWait_Data extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } +} +export class FSMSendMsgWait extends OBInstruction { + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } +} +export class FSMBroadcastMsgWait extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} +export class TextJoin extends OBInstruction { + Left; + Right; + RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } +} +export class ToString extends OBInstruction { + ValueType; + ValueRegIdx; + RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } +} +export class Sender extends OBInstruction { + RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } +} +export class SHL extends OBInstruction { + value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } +} +export class AND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } +} +export class FIX extends OBInstruction { + regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } +} +/** + * value of may by key + */ +export class VOM extends OBInstruction { + map; + key; + ValueType; + RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } +} +export class LAND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } +} +export class LOR extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 0 : 1; + } + }; + } +} +export class LNOT extends OBInstruction { + a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } +} +export class COND extends OBInstruction { + if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } +} +export class NEW extends OBInstruction { + StructDef; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFFF000) >> 12; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } +} \ No newline at end of file -- Gitee From 887cf06912a1653a679dfb0a3b7b9cd3dd4e2fa6 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Fri, 22 Oct 2021 12:33:24 +0800 Subject: [PATCH 03/30] =?UTF-8?q?=E7=89=88=E6=9D=83=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- hap/entry/src/main/js/default/common/canvas.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index 0fe2e8f..eebb39b 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -1,3 +1,8 @@ +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 + */ export class OBCanvas2D { /** * @type {HTMLCanvasElement} -- Gitee From f4cdee3044fecb801cf2740ad08a9ec83ed7182b Mon Sep 17 00:00:00 2001 From: duzc2 Date: Fri, 22 Oct 2021 12:55:24 +0800 Subject: [PATCH 04/30] =?UTF-8?q?=E7=89=88=E6=9D=83=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- .../src/main/js/default/common/canvas.js | 21 +++++++++++++------ .../js/default/common/runtime/debugger.js | 20 ++++++++++++------ .../main/js/default/common/runtime/util.js | 14 +++++++++++++ .../src/main/js/default/common/runtime/vm.js | 17 +++++++++++---- .../src/main/js/default/pages/index/index.css | 2 +- .../src/main/js/default/pages/index/index.js | 3 +-- 6 files changed, 58 insertions(+), 19 deletions(-) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index eebb39b..e656c47 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -1,7 +1,16 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ export class OBCanvas2D { /** @@ -28,7 +37,7 @@ export class OBCanvas2D { } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.fillStyle = str_color.substr(0,7); + this.canvas2dctx.fillStyle = str_color.substr(0, 7); } setStrokeStyleColor(color) { let str_color; @@ -38,7 +47,7 @@ export class OBCanvas2D { } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.fillStyle = str_color.substr(0,7); + this.canvas2dctx.fillStyle = str_color.substr(0, 7); } /** * 安装到脚本库 diff --git a/hap/entry/src/main/js/default/common/runtime/debugger.js b/hap/entry/src/main/js/default/common/runtime/debugger.js index 9c9e2f6..a56d303 100644 --- a/hap/entry/src/main/js/default/common/runtime/debugger.js +++ b/hap/entry/src/main/js/default/common/runtime/debugger.js @@ -1,6 +1,14 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 - */ - +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/util.js b/hap/entry/src/main/js/default/common/runtime/util.js index 9723535..9a7c777 100644 --- a/hap/entry/src/main/js/default/common/runtime/util.js +++ b/hap/entry/src/main/js/default/common/runtime/util.js @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import util from '@ohos.util' let _TextDecoder = util.TextDecoder; export { _TextDecoder as TextDecoder }; \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js index 071aed0..43478a9 100644 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ b/hap/entry/src/main/js/default/common/runtime/vm.js @@ -1,7 +1,16 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ import * as util from './util.js' export class NativeUtil { diff --git a/hap/entry/src/main/js/default/pages/index/index.css b/hap/entry/src/main/js/default/pages/index/index.css index f8f510e..280f036 100644 --- a/hap/entry/src/main/js/default/pages/index/index.css +++ b/hap/entry/src/main/js/default/pages/index/index.css @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 Du Tian Wei * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/hap/entry/src/main/js/default/pages/index/index.js b/hap/entry/src/main/js/default/pages/index/index.js index f10700b..b8f546a 100644 --- a/hap/entry/src/main/js/default/pages/index/index.js +++ b/hap/entry/src/main/js/default/pages/index/index.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 Du Tian Wei * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import router from '@system.router'; import fileio from '@ohos.fileio'; import * as obvm from '../../common/runtime/vm.js'; -- Gitee From c13b633133de0410bd7c1231e13cf94967cb0ff0 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Fri, 22 Oct 2021 12:55:24 +0800 Subject: [PATCH 05/30] =?UTF-8?q?=E7=89=88=E6=9D=83=E5=A4=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- .../src/main/js/default/common/canvas.js | 21 +++++++++++++------ .../js/default/common/runtime/debugger.js | 20 ++++++++++++------ .../main/js/default/common/runtime/util.js | 14 +++++++++++++ .../src/main/js/default/common/runtime/vm.js | 17 +++++++++++---- .../src/main/js/default/pages/index/index.css | 2 +- .../src/main/js/default/pages/index/index.js | 3 +-- 6 files changed, 58 insertions(+), 19 deletions(-) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index eebb39b..e656c47 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -1,7 +1,16 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ export class OBCanvas2D { /** @@ -28,7 +37,7 @@ export class OBCanvas2D { } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.fillStyle = str_color.substr(0,7); + this.canvas2dctx.fillStyle = str_color.substr(0, 7); } setStrokeStyleColor(color) { let str_color; @@ -38,7 +47,7 @@ export class OBCanvas2D { } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.fillStyle = str_color.substr(0,7); + this.canvas2dctx.fillStyle = str_color.substr(0, 7); } /** * 安装到脚本库 diff --git a/hap/entry/src/main/js/default/common/runtime/debugger.js b/hap/entry/src/main/js/default/common/runtime/debugger.js index 9c9e2f6..a56d303 100644 --- a/hap/entry/src/main/js/default/common/runtime/debugger.js +++ b/hap/entry/src/main/js/default/common/runtime/debugger.js @@ -1,6 +1,14 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 - */ - +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/util.js b/hap/entry/src/main/js/default/common/runtime/util.js index 9723535..9a7c777 100644 --- a/hap/entry/src/main/js/default/common/runtime/util.js +++ b/hap/entry/src/main/js/default/common/runtime/util.js @@ -1,3 +1,17 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ import util from '@ohos.util' let _TextDecoder = util.TextDecoder; export { _TextDecoder as TextDecoder }; \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js index 071aed0..43478a9 100644 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ b/hap/entry/src/main/js/default/common/runtime/vm.js @@ -1,7 +1,16 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ import * as util from './util.js' export class NativeUtil { diff --git a/hap/entry/src/main/js/default/pages/index/index.css b/hap/entry/src/main/js/default/pages/index/index.css index f8f510e..280f036 100644 --- a/hap/entry/src/main/js/default/pages/index/index.css +++ b/hap/entry/src/main/js/default/pages/index/index.css @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 Du Tian Wei * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at diff --git a/hap/entry/src/main/js/default/pages/index/index.js b/hap/entry/src/main/js/default/pages/index/index.js index f10700b..b8f546a 100644 --- a/hap/entry/src/main/js/default/pages/index/index.js +++ b/hap/entry/src/main/js/default/pages/index/index.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Huawei Device Co., Ltd. + * Copyright (c) 2020-2021 Du Tian Wei * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -12,7 +12,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - import router from '@system.router'; import fileio from '@ohos.fileio'; import * as obvm from '../../common/runtime/vm.js'; -- Gitee From b722741b9b4574ed3be0ec4de29b913563abe834 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sun, 24 Oct 2021 03:15:42 +0800 Subject: [PATCH 06/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BA=8B=E4=BB=B6bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/js/default/pages/index/index.hml | 26 ++++++++------ .../src/main/js/default/pages/index/index.js | 34 +++++++++++++++++-- 2 files changed, 46 insertions(+), 14 deletions(-) diff --git a/hap/entry/src/main/js/default/pages/index/index.hml b/hap/entry/src/main/js/default/pages/index/index.hml index 03298ce..f4ed250 100644 --- a/hap/entry/src/main/js/default/pages/index/index.hml +++ b/hap/entry/src/main/js/default/pages/index/index.hml @@ -11,18 +11,22 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. + ontouchstart="ob_touchstart" + ontouchmove="ob_touchmove" ontouchcancel="ob_touchcancel" + ontouchend="ob_touchend" onlongpress="ob_longpress" + + onclick="ob_click" --> - - -
- -
- + +
+ +
+ +
- \ No newline at end of file +
\ No newline at end of file diff --git a/hap/entry/src/main/js/default/pages/index/index.js b/hap/entry/src/main/js/default/pages/index/index.js index b8f546a..e317d75 100644 --- a/hap/entry/src/main/js/default/pages/index/index.js +++ b/hap/entry/src/main/js/default/pages/index/index.js @@ -21,7 +21,7 @@ import prompt from '@system.prompt'; let filepath = '/data/openblock.xe'; export default { data: { - info: null, + info: "info:", vm: null, fsm: null, uninited: true, @@ -32,11 +32,39 @@ export default { type: 'button' }] }, + log(s) { + this.info = s; + }, ob_event(name) { - if (this.fsm) { - this.fsm.PostMessage(new obvm.OBEventMessage(name, null, null, this)); + this.log(name); + try { + if (this.vm) { + this.log("1"); + this.vm.BroadcastMessage(new obvm.OBEventMessage(name, "", null, null)); + this.log("2"); + } + } catch (e) { + this.log(e + ""); } }, + ob_click(e) { + this.ob_event("click"); + }, + touchStart(e) { + this.ob_event("touchstart"); + }, + ob_touchmove(e) { + this.ob_event("touchmove"); + }, + ob_touchend(e) { + this.ob_event("touchend"); + }, + ob_longpress(e) { + this.ob_event("longpress"); + }, + ob_swipe(e) { + this.ob_event("swipe"); + }, initStage() { let stage = this.$refs.canvas1; try { -- Gitee From 15fd53f68110c4fa681447c930017d213dff71d7 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Thu, 4 Nov 2021 13:57:07 +0800 Subject: [PATCH 07/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=AD=90=E7=AA=97?= =?UTF-8?q?=E5=8F=A3=E5=85=B3=E9=97=AD=E4=B8=8D=E4=BA=86=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- connector/openharmonyconnector.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/connector/openharmonyconnector.js b/connector/openharmonyconnector.js index b784fa3..351a3de 100644 --- a/connector/openharmonyconnector.js +++ b/connector/openharmonyconnector.js @@ -64,7 +64,7 @@ if (!err) { let runProjectCmd = { "cmd": "runProject", "bytes": result, fsm: "Start.Main" }; if (!JSPreviewer_iframe) { - UB_IDE.addSubwindowComponent('jspreviewer'); + UB_IDE.ensureSubwindowComponent('jspreviewer'); setTimeout(() => { JSPreviewer_iframe.contentWindow.window.onload = () => { JSPreviewer_iframe.contentWindow.postMessage(runProjectCmd); -- Gitee From 349432f117581104ab758c9cfb13bd85304fa3ee Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sun, 14 Nov 2021 15:33:17 +0800 Subject: [PATCH 08/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20vm.js?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- .../src/main/js/default/common/runtime/vm.js | 8747 +++++++++-------- 1 file changed, 4408 insertions(+), 4339 deletions(-) diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js index 43478a9..85fd462 100644 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ b/hap/entry/src/main/js/default/common/runtime/vm.js @@ -1,4341 +1,4410 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import * as util from './util.js' -export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); - }); - }; - return f; - } -} -export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @1type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {number} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } -} -export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int -} -export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; -} -export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } -} -export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; -} -export class OBCodeSegment { - name; - functions; - fsms; -} -export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - Statements; -} -export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - /** - * @type {string} - */ - ModuleName; -} -export class OBMessageHandler { - Name; - Func; - ArgTypeName; -} -export class OBEventHandler { - Name; - Func; -} -export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } -} -export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - return new STMT_start(); - case 9: - return new B_STMT_end(); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - case 59: - return new NEW(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } -} -export class PositionUpdatePair { - targetOffset; - callback; -} -export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - CurrentStatementStack = []; //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {OBStructValue} - */ - /** - * @type {Array} StructRegister[] - */ - StructRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {object} - */ - /** - * @type {Array} NObjectRegister[] - */ - NObjectRegister; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - varInfo[i] = info; - } - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength / 4; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset === this.currentInstructPosition) { - p.callback(newPos); - } - }); - } -} - -export class OBBuildInFunctions{ - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward === 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } -}; -export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(null); - registers.LongRegister = []; - registers.LongRegister.fill(0, 0, Def.IntegerCnt); - registers.DoubleRegister = []; - registers.DoubleRegister.fill(0, 0, Def.FloatCnt); - registers.StringRegister = []; - registers.StringRegister.fill('', 0, Def.StringCnt); - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } -} -export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @1param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - if (type.startsWith("S") && type.endsWith(";")) { - type = type.substr(1, type.length - 2); - } - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - let def = this.StructDef[type]; - let group = this.Groups[type]; - let reader = group.Data; - let itemStart = 0; - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid === id) { - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - } - throw Error("找不到 ID为" + id + "的" + type); - } -} - -export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBufferReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } -} -class Relocation { - /** - * @1type {Object.:{idx:Number,inited:bool}>} - */ - string = {}; - /** - * @1type {Object.} - */ - integer = {}; - /** - * @1type {Object.} - */ - float = {}; - /** - * @1type {Object.} - */ - bin = {}; - /** - * @1type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } -} -export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw Error("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName === s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - let typeIdx = reader.ReadInt32(); - let count = reader.ReadInt32(); - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadInt32(); - let d = {}; - let cnt = reader.ReadInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } -} - -export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(start, true); - if (length === 0) { - return ""; - } - let ab = this.buf.slice(start + 4, start + 4 + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - let str = utf8decoder.decode(ui8); - if (str === null) { - throw Error('no string value of idx:' + stringIdx); - } - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - let buf; - if (typeof (length) === "undefined") { - buf = this.buf.slice(pos); - } else { - buf = this.buf.slice(pos, pos + length); - } - return new OBArrayBufferReader(buf); - } - - seek(pos) { - if (typeof (pos) === "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } -} - - -export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - this.Actions.push(Instruction); - } -} -// 虚拟机 - -export class VMInterruptException { -} -export class ChangeStateException extends VMInterruptException { -} -export class ChangeDestroyException extends VMInterruptException { -} -export class OBVM { - /** - * @1type {function(any)} - */ - Output; - /** - * typeName->[VMFSM] - * @1type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @1type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f === fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {*} callback - */ - Schedule(millisecond, callback) { - setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } -} -export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null,null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.data.Name); - } - } -} -export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.LongRegister = []; - this.LongRegister.length = v.count; - this.LongRegister.fill(0); - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.DoubleRegister = []; - this.DoubleRegister.length = v.count; - this.DoubleRegister.fill(0); - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StringRegister = []; - this.StringRegister.length = v.count; - this.StringRegister.fill(""); - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StructRegister = []; - this.StructRegister.length = v.count; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.NObjectRegister = []; - this.NObjectRegister.length = v.count; - break; - default: - throw Error("Unknown type " + v.typeIdx); - } - }); - } -} -export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {OBTypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let h = this.data.EventHandlers[msg.name]; - if (h) { - this.currentMessage = msg; - new OBVMFunction(h.Func).Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let hl = this.data.MessageHandlers[m.name]; - if (hl) { - hl.forEach(h => { - if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { - new OBVMFunction(h.Func).Call(this); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } -} -export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {OBTypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc, builder, args) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - if (builder) { - /** - * @1type {List>();} - */ - let LongRegister_ = []; - let DoubleRegister_ = [];// new List>(); - let StringRegister_ = [];// new List>(); - let StructRegister_ = [];// new List>(); - let NObjectRegister_ = [];//new List>(); - - for (let i = 1; i < args.length; i++) { - let arg = args[i]; - let Register = arg & 0xFFF; - let RegisterType = (arg >> 12) & 0xF; - - switch (RegisterType) { - case 0: - LongRegister_.push(builder.LongRegister[Register]); - break; - case 1: - DoubleRegister_.push(builder.DoubleRegister[Register]); - break; - case 2: - StringRegister_.push(builder.StringRegister[Register]); - break; - case 3: - StructRegister_.push(builder.StructRegister[Register]); - break; - case 4: - NObjectRegister_.push(builder.NObjectRegister[Register]); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - if (LongRegister_.length > 0) { - this.LongRegister = LongRegister_; - } - if (DoubleRegister_.length > 0) { - this.DoubleRegister = DoubleRegister_; - } - if (StringRegister_.length > 0) { - this.StringRegister = StringRegister_; - } - if (StructRegister_.length > 0) { - this.StructRegister = StructRegister_; - } - if (NObjectRegister_.length > 0) { - this.NObjectRegister = NObjectRegister_; - } - } - } - /** - * - * @param {OBVMState} state - */ - Call(state, uBFunction, localVars) { - if (uBFunction) { - if (this.LongRegister != null) { - for (let i = 0; i < this.LongRegister.length; i++) { - this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); - } - } - if (this.DoubleRegister != null) { - for (let i = 0; i < this.DoubleRegister.length; i++) { - this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); - } - } - if (this.StringRegister != null) { - for (let i = 0; i < this.StringRegister.length; i++) { - this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); - } - } - if (this.StructRegister != null) { - for (let i = 0; i < this.StructRegister.length; i++) { - this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); - } - } - if (this.NObjectRegister != null) { - for (let i = 0; i < this.NObjectRegister.length; i++) { - this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); - } - } - } - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType === 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType === 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType === 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType === 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType === 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } -} -export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return arg.Def.Name; - case 4: - // return "NObject"; - if (arg.constructor === OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } -} -export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } -} -export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } -} -// 字节码 -export class STMT_start extends OBInstruction { - StatementContext; - - init(code, builder, instructions, i) { - this.StatementContext = new OBStatementContext(); - this.StatementContext.InstPos = this.Position; - } - - link(builder, instructions, i) { - if (builder.CurrentStatementStack.length > 0) { - let Actions = null; - builder.PushAction((st, uf, locals, pos) => { - if (Actions == null) { - Actions = this.StatementContext.Actions; - } - for (let i = 0; i < Actions.length;) { - let action = Actions[i]; - i = action(st, uf, locals, i); - } - return pos + 1; - }); - } - builder.CurrentStatementStack.push(this.StatementContext); - } -} -export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFFF000) >> 12; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } -} -export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } -} -export class B_STMT_end extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - let sc = builder.CurrentStatementStack.pop(); - if (builder.CurrentStatementStack.length === 0) { - builder.RootStatementContext = sc; - } - } -} -export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } -} -export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } -} -export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } -} -export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } -} -export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } -} -export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } -} -export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } -} -export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } -} -export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } -} -export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } -} -export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } -} -export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister === -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } -} -export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } -} -export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } -} -export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } -} -export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } -} - -export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } -} -export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFFF000) >> 12); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } -} -export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFF; - switch (specal) { - case 0xFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFFF000) >> 12); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } -} -export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } -} -export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } -} -export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } else { - fsm.Target = st.fsm.Target; - } - return fsm; - }; - } -} -export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} -export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } -} - -export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } -} -export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - let enable = true; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - if (enable) { - enable = false; - let v = LongReg(st, uf, locals); - return v - 1; - } else { - throw Error("reentry"); - } - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - if (enable) { - enable = false; - let v = DoubleReg(st, uf, locals); - return v - 1; - } else { - throw Error("reentry"); - } - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } -} -export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } -} -export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } -} -export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } -} -export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } -} - -export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } -} -export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} - -/** - * 单元数操作 - */ -export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } -} -export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } -} -export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } -} -export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } -} -export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } -} -export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} -export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } -} -export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } -} -export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } -} -export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } -} -export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } -} -export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } -} /** - * value of may by key + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 */ -export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } -} -export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return c ? 1 : 0; - } else { - return 0; - } - }; - } -} -export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return c ? 0 : 1; - } - }; - } -} -export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return v === 0 ? 1 : 0; - }; - } -} -export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } -} -export class NEW extends OBInstruction { - StructDef; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Register = (code & 0xFFF000) >> 12; - - let structType = builder.loader.data.GetString(stridx); - let structDef = builder.loader.script.StructDef[structType]; - if (!structDef) { - throw Error('不存在数据结构 ' + structType); - } - this.StructDef = structDef; - } - - link(builder, instructions, idx) { - builder.StructRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - let s = new OBStructValue(this.StructDef); - return s; - } -} \ No newline at end of file + import * as util from './util.js' + export class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + static objFieldGetter(fieldName, fieldRegister) { + return (builder, args) => { + let obj = builder.NObjectRegister[args[1] & 0xfff]; + builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { + return obj(st, f, local)[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + if (typeof (v) != 'function') { + debugger + } + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + func.apply(null, argVals); + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + return func.apply(null, argVals); + }); + }; + return f; + } + } + export class OBScript { + NativeLibHash = {}; // libname->hash + InstalledLibs = {}; + NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + StructDef = {}; // typename-> def + loadedFunctions; //= {};//function sign->function + FullNameFSMData = {}; //FullName->OBFSM + + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } + } + export class OBStructDef { + Name; //string + StructCnt; // int + StringCnt; // int + IntegerCnt; // int + FloatCnt; // int + NobjectCnt; // int + StructFields; // int + } + export class OBStructValueData { + /** + * @type {OBArrayBufferReader} + */ + Data; //arraybuffer + FullName; + Offset; + Length; + StructCount; + } + export class OBVariableInfo { + typeIdx; + count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } + } + export class OBState { + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + Name; + MessageHandlers; + EventHandlers; + } + export class OBCodeSegment { + name; + functions; + fsms; + } + export class OBFunction { + /** + * @type {OBVariableInfo[]} + */ + Variables; + instructions; + /** + * @type {String} + */ + Signure; + Statements; + } + export class OBFSM { + /** + * @type {string} + */ + Name; + /** + * @type {Object.} + */ + States; //string->state + /** + * @type {OBState} + */ + Entry; //state + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + FullName; + /** + * @type {string} + */ + ModuleName; + } + export class OBMessageHandler { + Name; + Func; + ArgTypeName; + } + export class OBEventHandler { + Name; + Func; + } + export class OBInstruction { + Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } + } + export class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + return new STMT_start(); + case 9: + return new B_STMT_end(); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } + } + export class PositionUpdatePair { + targetOffset; + callback; + } + export class OBFunctionBuilder { + loader; //OBScriptLoader + StatementLength; //integer + BuildingFunc; //OBFunction + PositionUpdatePairList; + currentInstructPosition; //integer + CurrentStatementStack = []; //[StatementContext] + + /** + * @callback LongRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type LongRegister[] + */ + LongRegister; + /** + * @callback DoubleRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type DoubleRegister[] + */ + DoubleRegister; + /** + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {string} + */ + /** + * @type StringRegister[] + */ + StringRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {OBStructValue} + */ + /** + * @type {Array} StructRegister[] + */ + StructRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {object} + */ + /** + * @type {Array} NObjectRegister[] + */ + NObjectRegister; + + constructor(loader) { + this.loader = loader; + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength / 4; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } + } + + export class OBBuildInFunctions { + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } + } + export class OBStructValue { + /** + * @type {OBStructDef} + */ + Def; + /** + * @type {OBTypedVariableGroup} + */ + registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } + } + export class StructData { + /** + * @type {Object.} + */ + StructDef; + /** + * @type {Object.} + */ + Groups; + /** + * @type {OBArrayBufferReader} + */ + DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } + } + + export class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } + } + class Relocation { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + string = {}; + /** + * @1type {Object.} + */ + integer = {}; + /** + * @1type {Object.} + */ + float = {}; + /** + * @1type {Object.} + */ + bin = {}; + /** + * @1type {Object.} + */ + structFieldIndex = {}; + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } + } + export class OBScriptLoader { + /** + * @type {OBArrayBufferReader} + */ + reader; //OBArrayBufferReader + /** + * @type {OBArrayBufferReader} + */ + data; //OBArrayBufferReader + loadingFunctions = {}; //[OBFunctionBuilder] + Linkings = []; //Linkable + + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + let typeIdx = reader.ReadInt32(); + let count = reader.ReadInt32(); + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadInt32(); + let d = {}; + let cnt = reader.ReadInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } + } + + export class OBArrayBufferReader { + /** + * @type {Number} integer of position + */ + pos; // int + /** + * @type {ArrayBuffer} + */ + buf; // ArrayBuffer + /** + * @type DataView + */ + view; // DataView + /** + * @type {Object.} + */ + stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.view = new DataView(buf); + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(start, true); + if (length === 0) { + return ""; + } + let ab = this.buf.slice(start + 4, start + 4 + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + let str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + let buf; + if (typeof (length) === "undefined") { + buf = this.buf.slice(pos); + } else { + buf = this.buf.slice(pos, pos + length); + } + return new OBArrayBufferReader(buf); + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } + } + + + export class OBStatementContext { + InstPos; + Actions = []; + + PushAction(Instruction) { + this.Actions.push(Instruction); + } + } + // 虚拟机 + + export class VMInterruptException { + } + export class ChangeStateException extends VMInterruptException { + } + export class ChangeDestroyException extends VMInterruptException { + } + export class OBVM { + /** + * @1type {function(any)} + */ + Output; + /** + * typeName->[VMFSM] + * @1type {Object.} + */ + Running = {}; + /** + * @type OBScript + */ + script; + /** + * @1type {OBVMFSM} + */ + Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script) { + if (!script) { + throw Error("Script is null"); + } + this.script = script; + } + + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } + } + export class OBVMFSM { + static ID_GEN = 0; + /** + * @type {any} + */ + Target; + /** + * @type {OBFSM} + */ + data; + id; + /** + * @type {OBVMState} + */ + CurrentState; + /** + * @type {OBVMState[]} + */ + StateStack = []; + /** + * @type {OBVM} + */ + VM; + Inbox = []; + PrioritizedInbox = []; + VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.data = data; + this.id = ++OBVMFSM.ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } + } + export class OBTypedVariableGroup { + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } + } + export class OBVMState { + /** + * @type {OBState} + */ + data; + /** + * @type {OBVMFSM} + */ + fsm; + /** + * @type {OBTypedVariableGroup} + */ + VariableGroup; + /** + * @type {OBMessage} + */ + currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } + } + export class OBVMFunction { + /** + * @type {OBFunction} + */ + data; + /** + * @type {OBTypedVariableGroup} + */ + LocalVar; + returnType = -1; + returnValue; + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } + } + export class OBMessage { + name; + arg; + argType; + sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } + } + export class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } + } + export class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } + } + // 字节码 + export class STMT_start extends OBInstruction { + StatementContext; + + init(code, builder, instructions, i) { + this.StatementContext = new OBStatementContext(); + this.StatementContext.InstPos = this.Position; + } + + link(builder, instructions, i) { + if (builder.CurrentStatementStack.length > 0) { + let Actions = null; + builder.PushAction((st, uf, locals, pos) => { + if (Actions == null) { + Actions = this.StatementContext.Actions; + } + for (let i = 0; i < Actions.length;) { + let action = Actions[i]; + i = action(st, uf, locals, i); + } + return pos + 1; + }); + } + builder.CurrentStatementStack.push(this.StatementContext); + } + } + export class LDSTR extends OBInstruction { + Value; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } + } + export class PRT extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } + } + export class B_STMT_end extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + let sc = builder.CurrentStatementStack.pop(); + if (builder.CurrentStatementStack.length === 0) { + builder.RootStatementContext = sc; + } + } + } + export class ReceivedMessage extends OBInstruction { + typeId; + Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } + } + export class STVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + export class STVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + export class StructFieldDesc extends OBInstruction { + fieldTypeId; + fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } + } + export class GetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + return stt.registers.LongRegister[fieldIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + export class SetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + export class CHSTT extends OBInstruction { + StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } + } + export class MethodCallRegisterInfoAnchor extends OBInstruction { + RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } + } + export class NativeMethodCall extends OBInstruction { + LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } + } + export class FSMVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + export class SLF extends OBInstruction { + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } + } + export class MethodCall extends OBInstruction { + MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } + } + export class BRIFN extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } + } + export class BR extends OBInstruction { + Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } + } + export class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } + } + export class ARITHF extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } + } + + export class ARITHI extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } + } + export class LDI extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } + } + export class LDF extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFFF; + switch (specal) { + case 0xFFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } + } + export class RET extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } + } + export class FSMVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + export class CreateFSM extends OBInstruction { + FSMTypeName; + ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } + } + export class FSMSendMsg extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + export class GZ0 extends OBInstruction { + VarType; + VarIdx; + ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } + } + + export class BRIF extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } + } + export class DEC extends OBInstruction { + regType; + regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + let v = LongReg(st, uf, locals); + return v - 1; + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + let v = DoubleReg(st, uf, locals); + return v - 1; + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } + } + export class Reg2Var extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + export class Var2Reg extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + export class I2F extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } + } + export class EQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class NEQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class LT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class LTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class GT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + + export class GTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } + } + export class FSMBroadcastMsg extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + + /** + * 单元数操作 + */ + export class SGLF extends OBInstruction { + Opcode; + value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } + } + export class RAND extends OBInstruction { + Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } + } + export class F2I extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } + } + export class FSMSendMsgWait_Data extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + } + export class FSMSendMsgWait extends OBInstruction { + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } + } + export class FSMBroadcastMsgWait extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + export class TextJoin extends OBInstruction { + Left; + Right; + RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } + } + export class ToString extends OBInstruction { + ValueType; + ValueRegIdx; + RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + export class Sender extends OBInstruction { + RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } + } + export class SHL extends OBInstruction { + value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } + } + export class AND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } + } + export class FIX extends OBInstruction { + regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } + } + /** + * value of may by key + */ + export class VOM extends OBInstruction { + map; + key; + ValueType; + RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + export class LAND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } + } + export class LOR extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 0 : 1; + } + }; + } + } + export class LNOT extends OBInstruction { + a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } + } + export class COND extends OBInstruction { + if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } + } + export class NEW extends OBInstruction { + StructDef; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFF0000) >> 16; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } + } + + export class OBStructDataSerializer { + relocation = new Relocation(); + /** + * + * @param {OBStructValue[]} valueData + * @returns {int[]} + */ + serialize(valueDataArray) { + let group = this.groupData(valueDataArray); + } + /** + * + * @param {OBStructValue[]} valueDataArray + * @returns {Object. { + let list = group[d.Def.Name]; + if (!list) { + list = []; + group[d.Def.Name] = list; + } + this.collData(d); + list.push(d); + }); + return group; + } + /** + * + * @param {OBStructValue} d + */ + collData(d) { + d.string.forEach(str => { + this.relocation.addRelocationString(str); + }); + d.registers.object.forEach(ofd => { + switch (ofd.type.$__type) { + case "StructFieldTypeStruct": + break; + case "StructFieldTypeIntegerMap": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + break; + case "StructFieldTypeStringMap": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + break; + case "StructFieldTypeList": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + break; + default: + console.error(ofd); + throw Error("功能未实现 " + ofd.type.$__type); + } + }); + } + } \ No newline at end of file -- Gitee From 6dbd34826d9bb5eb3786f384f88b9a6ca8aae54b Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sun, 14 Nov 2021 23:27:51 +0800 Subject: [PATCH 09/30] fix setStrokeStyleColor Signed-off-by: duzc2 --- hap/entry/src/main/js/default/common/canvas.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index e656c47..e9c3bd6 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -47,7 +47,7 @@ export class OBCanvas2D { } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.fillStyle = str_color.substr(0, 7); + this.canvas2dctx.strokeStyle = str_color.substr(0, 7); } /** * 安装到脚本库 -- Gitee From f063b246909a07ef6124fa2db7c178dca02ad07d Mon Sep 17 00:00:00 2001 From: duzc2 Date: Tue, 15 Feb 2022 05:17:31 +0800 Subject: [PATCH 10/30] =?UTF-8?q?=E6=9B=B4=E6=96=B0UI=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- connector/openharmonyconnector.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/connector/openharmonyconnector.js b/connector/openharmonyconnector.js index 351a3de..8ee3d84 100644 --- a/connector/openharmonyconnector.js +++ b/connector/openharmonyconnector.js @@ -33,7 +33,7 @@ if (!v) { JSPreviewer = null; JSPreviewer_iframe = null; - UB_IDE.removeSubwindowComponent('jspreviewer'); + UB_IDE.removeExtComponent('subwindows','jspreviewer'); } } } @@ -64,7 +64,7 @@ if (!err) { let runProjectCmd = { "cmd": "runProject", "bytes": result, fsm: "Start.Main" }; if (!JSPreviewer_iframe) { - UB_IDE.ensureSubwindowComponent('jspreviewer'); + UB_IDE.ensureExtComponent('subwindows','jspreviewer'); setTimeout(() => { JSPreviewer_iframe.contentWindow.window.onload = () => { JSPreviewer_iframe.contentWindow.postMessage(runProjectCmd); -- Gitee From b8b493fe697115548a94885a79e3ac73fc9bc90c Mon Sep 17 00:00:00 2001 From: duzc2 Date: Fri, 18 Feb 2022 18:32:26 +0800 Subject: [PATCH 11/30] update ob Signed-off-by: duzc2 --- .../src/main/js/default/common/canvas.js | 4 + .../src/main/js/default/common/runtime/vm.js | 148 +++++++++--------- 2 files changed, 79 insertions(+), 73 deletions(-) diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js index e9c3bd6..09c486d 100644 --- a/hap/entry/src/main/js/default/common/canvas.js +++ b/hap/entry/src/main/js/default/common/canvas.js @@ -81,6 +81,10 @@ export class OBCanvas2D { script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), + script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), + script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), ]); } } \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js index 85fd462..7270a66 100644 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ b/hap/entry/src/main/js/default/common/runtime/vm.js @@ -286,9 +286,9 @@ case 7: return new RET(); case 8: - return new STMT_start(); + throw Error("Unknown byte code command:" + cmd); case 9: - return new B_STMT_end(); + throw Error("Unknown byte code command:" + cmd); case 10: return new CHSTT(); case 11: @@ -405,7 +405,7 @@ BuildingFunc; //OBFunction PositionUpdatePairList; currentInstructPosition; //integer - CurrentStatementStack = []; //[StatementContext] + RootStatementContext = new OBStatementContext(); //[StatementContext] /** * @callback LongRegister @@ -462,6 +462,7 @@ * @type {Array} NObjectRegister[] */ NObjectRegister; + StatementLength; constructor(loader) { this.loader = loader; @@ -474,7 +475,7 @@ let header = reader.ReadUInt32(); let pos = reader.pos; - this.StatementLength = header * 4 - pos; + // this.StatementLength = header * 4 - pos; reader.pos = header * 4; let nameIdx = reader.ReadUInt32(); BuildingFunc.Signure = data.GetString(nameIdx); @@ -495,12 +496,13 @@ info.count = reader.ReadUInt32(); varInfo[i] = info; } + this.StatementLength = reader.ReadUInt32(); BuildingFunc.Variables = varInfo; reader.pos = pos; } loadStatement(reader) { - let length = this.StatementLength / 4; + let length = this.StatementLength; this.BuildingFunc.instructions = []; this.PositionUpdatePairList = []; //[PositionUpdatePair] for (let i = 0; i < length; i++) { @@ -540,7 +542,7 @@ } PushAction(Instruction) { - let stmt = this.CurrentStatementStack[this.CurrentStatementStack.length - 1]; + let stmt = this.RootStatementContext; let newPos = stmt.Actions.length; stmt.PushAction(Instruction); this.PositionUpdatePairList.forEach((p) => { @@ -697,7 +699,12 @@ let a2 = builder.StringRegister[typeIdx]; let StructData = builder.loader.script.StructData; builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let r = StructData.Get(a2(state, func, locals), a1(state, func, locals)); + let typename = a2(state, func, locals); + let id = a1(state, func, locals); + let r = StructData.Get(typename, id); + if(!r){ + throw `Can't find ${typename} which id is ${id}`; + } return r; }; } @@ -777,6 +784,9 @@ } let def = this.StructDef[type]; let group = this.Groups[type]; + if(!group){ + throw `There is no preset data of the type ${type}`; + } let reader = group.Data; let itemStart = 0; for (let i = 0; i < group.StructCount; i++) { @@ -847,7 +857,7 @@ * @returns {StructData} */ readStructData(reader, data) { - let length = reader.ReadInt32(); + let _length = reader.ReadInt32(); let structs = {}; let groupCnt = reader.ReadUInt32(); @@ -954,18 +964,18 @@ if (MAG != 0x5845557F) { throw Error("Unknown MAG:" + MAG); } - let version = this.reader.ReadInt32(); + let version = this.reader.ReadUInt32(); if (version != 1) { throw Error("Unsupported version." + version); } - let SegmentCnt = this.reader.ReadInt32(); + let SegmentCnt = this.reader.ReadUInt32(); let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; let codes = []; for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadInt32(); + let type = this.reader.ReadUInt32(); let startIn4Bytes = this.reader.ReadUInt32(); let start = headerEnd + startIn4Bytes * 4; let pos = this.reader.pos; @@ -1015,7 +1025,7 @@ let start = reader.pos; let SegmentReader = reader.getSub(start); - + let length = SegmentReader.ReadUInt32(); let header = SegmentReader.ReadUInt32() * 4; SegmentReader.pos = header; let segment = new OBCodeSegment(); @@ -1189,8 +1199,11 @@ } readVariable(reader) { - let typeIdx = reader.ReadInt32(); - let count = reader.ReadInt32(); + // let typeIdx = reader.ReadUInt32(); + // let count = reader.ReadInt32(); + let vari = reader.ReadUInt32(); + let count = vari & 0xFFFFFFF; + let typeIdx = vari >> 28; let v = new OBVariableInfo(typeIdx, count); return v; } @@ -1235,9 +1248,9 @@ loadStructDefDataSegment() { let reader = this.reader; let data = this.data; - let length = reader.ReadInt32(); + let length = reader.ReadUInt32(); let d = {}; - let cnt = reader.ReadInt32(); + let cnt = reader.ReadUInt32(); for (let i = 0; i < cnt; i++) { let nameIdx = reader.ReadUInt32(); let name = data.GetString(nameIdx); @@ -1268,19 +1281,19 @@ } loadDataSegment() { - let length = this.reader.ReadInt32(); + let length = this.reader.ReadUInt32(); return this.reader.readSub(length * 4); } loadPackageInfo() { let reader = this.reader; let data = this.data; - let depCnt = reader.ReadInt32(); + let depCnt = reader.ReadUInt32(); let err = []; for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadInt32(); + let nameIdx = reader.ReadUInt32(); let name = data.GetString(nameIdx); - let hashIdx = reader.ReadInt32(); + let hashIdx = reader.ReadUInt32(); let hash = data.GetString(hashIdx); let lhash = this.script.NativeLibHash[name]; if (!lhash) { @@ -1301,6 +1314,10 @@ * @type {Number} integer of position */ pos; // int + /** + * @type {Number} integer of start + */ + start; // int /** * @type {ArrayBuffer} */ @@ -1317,6 +1334,7 @@ constructor(buf) { this.buf = buf; this.pos = 0; + this.start = 0; this.view = new DataView(buf); } @@ -1327,7 +1345,8 @@ } getInt32(p) { - let v = this.view.getInt32(p, true); + let v = this.view.getInt32(this.start + p, true); + // let v = this.view.getInt32(p, true); return v; } @@ -1338,7 +1357,8 @@ } getUint32(p) { - let v = this.view.getUint32(p, true); + let v = this.view.getUint32(this.start + p, true); + // let v = this.view.getUint32(p, true); return v; } @@ -1348,25 +1368,33 @@ } getFloat(p) { - let v = this.view.getFloat32(p, true); + let v = this.view.getFloat32(this.start + p, true); + // let v = this.view.getFloat32(p, true); return v; } GetString(stringIdx) { + let str = this.stringCache[stringIdx]; + if (str) { + return str; + } let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(start, true); + let length = this.view.getUint32(this.start + start, true); if (length === 0) { return ""; } - let ab = this.buf.slice(start + 4, start + 4 + length); + start = this.start + start + 4; + // start = start + 4; + let ab = this.buf.slice(start, start + length); let ui8 = new Uint8Array(ab); let utf8decoder = new util.TextDecoder("utf-8", { fatal: true }); - let str = utf8decoder.decode(ui8); + str = utf8decoder.decode(ui8); if (str === null) { throw Error('no string value of idx:' + stringIdx); } + this.stringCache[stringIdx] = str; return str; } @@ -1377,13 +1405,18 @@ } getSub(pos, length) { - let buf; - if (typeof (length) === "undefined") { - buf = this.buf.slice(pos); - } else { - buf = this.buf.slice(pos, pos + length); - } - return new OBArrayBufferReader(buf); + // let buf; + // if (typeof (length) === "undefined") { + // buf = this.buf.slice(pos); + // } else { + // buf = this.buf.slice(pos, pos + length); + // } + // let reader = new OBArrayBufferReader(buf); + // reader.start = this.start + pos; + // return reader; + let reader = new OBArrayBufferReader(this.buf); + reader.start = this.start + pos; + return reader; } seek(pos) { @@ -1481,7 +1514,7 @@ update() { this._HandleOnePendingFSM(); - let timestamp = Date.now(); + // let timestamp = Date.now(); // JS不需要在VM中处理计划任务 // this._HandleSchedulingTask(timestamp); // this._InvokeScheduledTask(timestamp); @@ -1613,6 +1646,9 @@ } HandleAllMessages() { + if (!this.CurrentState) { + return; + } let msg; while (msg = this.PrioritizedInbox.shift()) { msg.Handle(this.CurrentState); @@ -2073,31 +2109,6 @@ } } // 字节码 - export class STMT_start extends OBInstruction { - StatementContext; - - init(code, builder, instructions, i) { - this.StatementContext = new OBStatementContext(); - this.StatementContext.InstPos = this.Position; - } - - link(builder, instructions, i) { - if (builder.CurrentStatementStack.length > 0) { - let Actions = null; - builder.PushAction((st, uf, locals, pos) => { - if (Actions == null) { - Actions = this.StatementContext.Actions; - } - for (let i = 0; i < Actions.length;) { - let action = Actions[i]; - i = action(st, uf, locals, i); - } - return pos + 1; - }); - } - builder.CurrentStatementStack.push(this.StatementContext); - } - } export class LDSTR extends OBInstruction { Value; Register; @@ -2155,17 +2166,6 @@ }); } } - export class B_STMT_end extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - let sc = builder.CurrentStatementStack.pop(); - if (builder.CurrentStatementStack.length === 0) { - builder.RootStatementContext = sc; - } - } - } export class ReceivedMessage extends OBInstruction { typeId; Register; @@ -2628,11 +2628,13 @@ checkRegType; checkRegIdx; targetOffset; + targetOffsetBak; init(code, builder, instructions, i) { this.checkRegType = ((code >> 20) & 0xf); this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffsetBak = this.targetOffset; builder.PositionUpdate(this.targetOffset * 4, (newPos) => { this.targetOffset = newPos; }); @@ -3171,7 +3173,7 @@ init(code, builder, instructions, i) { this.checkRegType = ((code >> 20) & 0xf); this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = (((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); builder.PositionUpdate(this.targetOffset * 4, (newPos) => { this.targetOffset = newPos; }); @@ -4244,7 +4246,7 @@ return 1; } else { let c = getC(st, f, l); - return c ? 0 : 1; + return c ? 1 : 0; } }; } -- Gitee From 758f8ac00cb34f2dceb87ec70307649c7592875d Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sun, 20 Feb 2022 01:15:49 +0800 Subject: [PATCH 12/30] update sdk7 --- .gitignore | 1 + hap/.gitignore | 16 + hap/README.md | 23 - hap/README_zh.md | 23 - hap/build.gradle | 25 +- hap/entry/.gitignore | 2 + hap/entry/build.gradle | 20 +- hap/entry/package.json | 1 + hap/entry/proguard-rules.pro | 1 + hap/entry/src/main/config.json | 18 +- hap/entry/src/main/js/MainAbility/app.js | 8 + .../src/main/js/MainAbility/common/canvas.js | 90 + .../src/main/js/MainAbility/common/common.css | 37 + .../common/component/ob_dynamic.hml | 5 + .../common/component/ob_dynamic.js | 8 + .../main/js/MainAbility/common/normalize.css | 0 .../js/MainAbility/common/runtime/debugger.js | 14 + .../js/MainAbility/common/runtime/util.js | 17 + .../main/js/MainAbility/common/runtime/vm.js | 4412 +++++++++++++++++ .../src/main/js/MainAbility/i18n/en-US.json | 11 + .../src/main/js/MainAbility/i18n/zh-CN.json | 11 + .../main/js/MainAbility/pages/index/index.css | 17 + .../main/js/MainAbility/pages/index/index.hml | 32 + .../main/js/MainAbility/pages/index/index.js | 131 + .../js/MainAbility/pages/second/second.css | 24 + .../js/MainAbility/pages/second/second.hml | 6 + .../js/MainAbility/pages/second/second.js | 12 + .../main/resources/base/element/string.json | 6 +- hap/gradle.properties | 13 + hap/gradle/wrapper/gradle-wrapper.jar | Bin 0 -> 58694 bytes hap/gradle/wrapper/gradle-wrapper.properties | 6 + hap/gradlew | 183 + hap/gradlew.bat | 103 + hap/local.properties | 9 +- hap/package.json | 1 + hap/settings.gradle | 15 - 36 files changed, 5203 insertions(+), 98 deletions(-) create mode 100644 hap/.gitignore delete mode 100644 hap/README.md delete mode 100644 hap/README_zh.md create mode 100644 hap/entry/.gitignore create mode 100644 hap/entry/package.json create mode 100644 hap/entry/proguard-rules.pro create mode 100644 hap/entry/src/main/js/MainAbility/app.js create mode 100644 hap/entry/src/main/js/MainAbility/common/canvas.js create mode 100644 hap/entry/src/main/js/MainAbility/common/common.css create mode 100644 hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.hml create mode 100644 hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js create mode 100644 hap/entry/src/main/js/MainAbility/common/normalize.css create mode 100644 hap/entry/src/main/js/MainAbility/common/runtime/debugger.js create mode 100644 hap/entry/src/main/js/MainAbility/common/runtime/util.js create mode 100644 hap/entry/src/main/js/MainAbility/common/runtime/vm.js create mode 100644 hap/entry/src/main/js/MainAbility/i18n/en-US.json create mode 100644 hap/entry/src/main/js/MainAbility/i18n/zh-CN.json create mode 100644 hap/entry/src/main/js/MainAbility/pages/index/index.css create mode 100644 hap/entry/src/main/js/MainAbility/pages/index/index.hml create mode 100644 hap/entry/src/main/js/MainAbility/pages/index/index.js create mode 100644 hap/entry/src/main/js/MainAbility/pages/second/second.css create mode 100644 hap/entry/src/main/js/MainAbility/pages/second/second.hml create mode 100644 hap/entry/src/main/js/MainAbility/pages/second/second.js create mode 100644 hap/gradle.properties create mode 100644 hap/gradle/wrapper/gradle-wrapper.jar create mode 100644 hap/gradle/wrapper/gradle-wrapper.properties create mode 100644 hap/gradlew create mode 100644 hap/gradlew.bat create mode 100644 hap/package.json diff --git a/.gitignore b/.gitignore index 3859507..e9b0cb8 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ build hap/.gradle/6.3/executionHistory/ hap/.gradle/6.3/fileHashes/ hap/.gradle/buildOutputCleanup/ +hap/local.properties diff --git a/hap/.gitignore b/hap/.gitignore new file mode 100644 index 0000000..fdc0c4a --- /dev/null +++ b/hap/.gitignore @@ -0,0 +1,16 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +/entry/.preview +.cxx +/node_modules diff --git a/hap/README.md b/hap/README.md deleted file mode 100644 index 948ae59..0000000 --- a/hap/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# AtomicLayout - -### Introduction - -This sample illustrates style attributes related to layout effect adaptation, including the hiding feature, proportion feature, and fixed ratio. - -With the hiding feature, you can adjust the display priority of components in a container in the horizontal or vertical direction. - -With the proportion feature, you can adjust the proportion of each component in a container so that each of them is always arranged in a proportional space of the container. - -You can scale up or down a component with fixed ratio while retaining its aspect ratio. - -### Usage - -In this sample, there are three buttons on the home screen. You can click them to display the corresponding screen. - -On the feature display screen, the rectangle in light yellow is a container, and it accommodates three components: A, B, and C. You can click the buttons to change the size of the components and display them in different ways. - -### Constraints - -- The hiding and proportion features must be used in a flex layout that does not support cross-row display. -- This sample can only be run on mini-system devices. - diff --git a/hap/README_zh.md b/hap/README_zh.md deleted file mode 100644 index fb0a13b..0000000 --- a/hap/README_zh.md +++ /dev/null @@ -1,23 +0,0 @@ -# 原子布局 - -### 简介 - -本示例展示了布局效果自适应的相关样式属性,包括隐藏能力、占比能力和固定比例。 - -隐藏能力:可以调整组件内元素水平/垂直方向的显示优先级。 - -占比能力:可以调整指定元素始终在容器的某一比例空间中进行布局。 - -固定比例:可以以固定的比例调整组件的宽高尺寸。 - -### 使用说明 - -本示例主界面为三个按钮,点击后在新页面分别展示。 - -在能力展示页面中,浅黄色背景为父容器,A、B、C为其中三个子元素,点击按钮可改变子容器大小,子元素显示会随之改变。 - -### 约束与限制 - -- 隐藏能力与占比能力需在非折行的flex布局中使用。 -- 本示例支持在轻量系统使用。 - diff --git a/hap/build.gradle b/hap/build.gradle index 4082e5e..c2c8bba 100644 --- a/hap/build.gradle +++ b/hap/build.gradle @@ -1,22 +1,10 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. apply plugin: 'com.huawei.ohos.app' +//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 ohos { - signingConfigs { - debug { - storeFile file('C:\\openharmony\\key1\\openharmony.p12') - storePassword '000000187A7DAD405B3FC2C0DD5A22D71E099DAF1952185044808317227A7B8E1222ADCFBF53B994' - keyAlias = 'openharmony' - keyPassword '000000187828397D1F90A82A02013CB2E0EE8914EB988241276E31A9C535BB1F75BE8D9D66EC3723' - signAlg = 'SHA256withECDSA' - profile file('C:\\openharmony\\key1\\SgnedReleasedProfileTemplate.p7b') - certpath file('C:\\openharmony\\key1\\openharmony.cer') - } - } - compileSdkVersion 6 - defaultConfig { - compatibleSdkVersion 6 - } + compileSdkVersion 7 + supportSystem "standard" } buildscript { @@ -27,10 +15,10 @@ buildscript { maven { url 'https://developer.huawei.com/repo/' } - jcenter() } dependencies { - classpath 'com.huawei.ohos:hap:2.4.5.0' + classpath 'com.huawei.ohos:hap:3.0.3.4' + classpath 'com.huawei.ohos:decctest:1.2.6.0' } } @@ -42,6 +30,5 @@ allprojects { maven { url 'https://developer.huawei.com/repo/' } - jcenter() } -} \ No newline at end of file +} diff --git a/hap/entry/.gitignore b/hap/entry/.gitignore new file mode 100644 index 0000000..7d5b7a9 --- /dev/null +++ b/hap/entry/.gitignore @@ -0,0 +1,2 @@ +/build +/node_modules diff --git a/hap/entry/build.gradle b/hap/entry/build.gradle index 88e1fd7..3e1591e 100644 --- a/hap/entry/build.gradle +++ b/hap/entry/build.gradle @@ -1,8 +1,20 @@ apply plugin: 'com.huawei.ohos.hap' +//For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 ohos { - compileSdkVersion 6 + signingConfigs { + debug { + storeFile file('C:\\openharmony\\key1\\openharmony.p12') + storePassword '000000187A7DAD405B3FC2C0DD5A22D71E099DAF1952185044808317227A7B8E1222ADCFBF53B994' + keyAlias = 'openharmony' + keyPassword '000000187828397D1F90A82A02013CB2E0EE8914EB988241276E31A9C535BB1F75BE8D9D66EC3723' + signAlg = 'SHA256withECDSA' + profile file('C:\\openharmony\\key1\\SgnedReleasedProfileTemplate.p7b') + certpath file('C:\\openharmony\\key1\\openharmony.cer') + } + } + compileSdkVersion 7 defaultConfig { - compatibleSdkVersion 6 + compatibleSdkVersion 7 } buildTypes { release { @@ -12,5 +24,5 @@ ohos { } } } - supportSystem "standard" -} \ No newline at end of file +} + diff --git a/hap/entry/package.json b/hap/entry/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/hap/entry/package.json @@ -0,0 +1 @@ +{} diff --git a/hap/entry/proguard-rules.pro b/hap/entry/proguard-rules.pro new file mode 100644 index 0000000..f7666e4 --- /dev/null +++ b/hap/entry/proguard-rules.pro @@ -0,0 +1 @@ +# config module specific ProGuard rules here. \ No newline at end of file diff --git a/hap/entry/src/main/config.json b/hap/entry/src/main/config.json index 81188f7..b26e079 100644 --- a/hap/entry/src/main/config.json +++ b/hap/entry/src/main/config.json @@ -1,16 +1,17 @@ { "app": { "bundleName": "com.openblock.ohos", + "vendor": "openblock", "version": { "code": 1000000, - "name": "1.0" + "name": "1.0.0" } }, "deviceConfig": {}, "module": { "package": "com.openblock.ohos", - "name": ".MainAbility", - "mainAbility": "com.openblock.ohos.MainAbility", + "name": ".MyApplication", + "mainAbility": ".MainAbility", "deviceType": [ "phone" ], @@ -32,10 +33,15 @@ ] } ], + "orientation": "portrait", + "visible": true, + "srcPath": "MainAbility", "name": ".MainAbility", + "srcLanguage": "js", "icon": "$media:icon", - "description": "$string:mainability_description", - "label": "$string:app_name", + "description": "$string:description_mainability", + "formsEnabled": false, + "label": "$string:entry_MainAbility", "type": "page", "launchType": "standard" } @@ -45,7 +51,7 @@ "pages": [ "pages/index/index" ], - "name": "default", + "name": ".MainAbility", "window": { "designWidth": 720, "autoDesignWidth": false diff --git a/hap/entry/src/main/js/MainAbility/app.js b/hap/entry/src/main/js/MainAbility/app.js new file mode 100644 index 0000000..6d060ff --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/app.js @@ -0,0 +1,8 @@ +export default { + onCreate() { + console.info("Application onCreate"); + }, + onDestroy() { + console.info("Application onDestroy"); + } +}; diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js new file mode 100644 index 0000000..09c486d --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class OBCanvas2D { + /** + * @type {HTMLCanvasElement} + */ + canvas; + /** + * @type {CanvasRenderingContext2D} + */ + canvas2dctx; + /** + * + * @param {HTMLCanvasElement} canvas + */ + constructor(canvas) { + this.canvas = canvas; + this.canvas2dctx = canvas.getContext('2d'); + } + setFillStyleColor(color) { + let str_color; + if (color < 0) { + str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) + str_color = '#' + str_color; + } else { + str_color = '#' + color.toString(16).padStart(8, '0'); + } + this.canvas2dctx.fillStyle = str_color.substr(0, 7); + } + setStrokeStyleColor(color) { + let str_color; + if (color < 0) { + str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) + str_color = '#' + str_color; + } else { + str_color = '#' + color.toString(16).padStart(8, '0'); + } + this.canvas2dctx.strokeStyle = str_color.substr(0, 7); + } + /** + * 安装到脚本库 + * @param {OBScript} script + */ + install(script) { + script.InstallLib("canvas2d", "canvas2d", [ + script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + // canvas2dctx.fillStyle=color + script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), + script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), + script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), + ]); + } +} \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/common.css b/hap/entry/src/main/js/MainAbility/common/common.css new file mode 100644 index 0000000..0806a85 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/common.css @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +.container { + width: 100%; + height: 100%; + align-items: center; + justify-content: center; + flex-direction: column; +} + +.box { + width: 100%; + align-items: center; + flex-direction: column; + background-color: bisque; +} + +.btn { + width: 60%; + height: 100px; + font-size: 40px; + margin-top: 20px; + color: #ff00ff7f; +} \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.hml b/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.hml new file mode 100644 index 0000000..62cc5f7 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.hml @@ -0,0 +1,5 @@ + +
+ {{title}} + +
\ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js b/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js new file mode 100644 index 0000000..19f1cef --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js @@ -0,0 +1,8 @@ + +export default { + props: { + title: { + default: 'title', + }, + }, +} \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/normalize.css b/hap/entry/src/main/js/MainAbility/common/normalize.css new file mode 100644 index 0000000..e69de29 diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/debugger.js b/hap/entry/src/main/js/MainAbility/common/runtime/debugger.js new file mode 100644 index 0000000..a56d303 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/runtime/debugger.js @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/util.js b/hap/entry/src/main/js/MainAbility/common/runtime/util.js new file mode 100644 index 0000000..9a7c777 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/runtime/util.js @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import util from '@ohos.util' +let _TextDecoder = util.TextDecoder; +export { _TextDecoder as TextDecoder }; \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js new file mode 100644 index 0000000..7270a66 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -0,0 +1,4412 @@ +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 + */ + import * as util from './util.js' + export class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + static objFieldGetter(fieldName, fieldRegister) { + return (builder, args) => { + let obj = builder.NObjectRegister[args[1] & 0xfff]; + builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { + return obj(st, f, local)[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + if (typeof (v) != 'function') { + debugger + } + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + func.apply(null, argVals); + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + return func.apply(null, argVals); + }); + }; + return f; + } + } + export class OBScript { + NativeLibHash = {}; // libname->hash + InstalledLibs = {}; + NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + StructDef = {}; // typename-> def + loadedFunctions; //= {};//function sign->function + FullNameFSMData = {}; //FullName->OBFSM + + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } + } + export class OBStructDef { + Name; //string + StructCnt; // int + StringCnt; // int + IntegerCnt; // int + FloatCnt; // int + NobjectCnt; // int + StructFields; // int + } + export class OBStructValueData { + /** + * @type {OBArrayBufferReader} + */ + Data; //arraybuffer + FullName; + Offset; + Length; + StructCount; + } + export class OBVariableInfo { + typeIdx; + count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } + } + export class OBState { + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + Name; + MessageHandlers; + EventHandlers; + } + export class OBCodeSegment { + name; + functions; + fsms; + } + export class OBFunction { + /** + * @type {OBVariableInfo[]} + */ + Variables; + instructions; + /** + * @type {String} + */ + Signure; + Statements; + } + export class OBFSM { + /** + * @type {string} + */ + Name; + /** + * @type {Object.} + */ + States; //string->state + /** + * @type {OBState} + */ + Entry; //state + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + FullName; + /** + * @type {string} + */ + ModuleName; + } + export class OBMessageHandler { + Name; + Func; + ArgTypeName; + } + export class OBEventHandler { + Name; + Func; + } + export class OBInstruction { + Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } + } + export class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + throw Error("Unknown byte code command:" + cmd); + case 9: + throw Error("Unknown byte code command:" + cmd); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } + } + export class PositionUpdatePair { + targetOffset; + callback; + } + export class OBFunctionBuilder { + loader; //OBScriptLoader + StatementLength; //integer + BuildingFunc; //OBFunction + PositionUpdatePairList; + currentInstructPosition; //integer + RootStatementContext = new OBStatementContext(); //[StatementContext] + + /** + * @callback LongRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type LongRegister[] + */ + LongRegister; + /** + * @callback DoubleRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type DoubleRegister[] + */ + DoubleRegister; + /** + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {string} + */ + /** + * @type StringRegister[] + */ + StringRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {OBStructValue} + */ + /** + * @type {Array} StructRegister[] + */ + StructRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {object} + */ + /** + * @type {Array} NObjectRegister[] + */ + NObjectRegister; + StatementLength; + + constructor(loader) { + this.loader = loader; + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + // this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + this.StatementLength = reader.ReadUInt32(); + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.RootStatementContext; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } + } + + export class OBBuildInFunctions { + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let typename = a2(state, func, locals); + let id = a1(state, func, locals); + let r = StructData.Get(typename, id); + if(!r){ + throw `Can't find ${typename} which id is ${id}`; + } + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } + } + export class OBStructValue { + /** + * @type {OBStructDef} + */ + Def; + /** + * @type {OBTypedVariableGroup} + */ + registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } + } + export class StructData { + /** + * @type {Object.} + */ + StructDef; + /** + * @type {Object.} + */ + Groups; + /** + * @type {OBArrayBufferReader} + */ + DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + if(!group){ + throw `There is no preset data of the type ${type}`; + } + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } + } + + export class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let _length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } + } + class Relocation { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + string = {}; + /** + * @1type {Object.} + */ + integer = {}; + /** + * @1type {Object.} + */ + float = {}; + /** + * @1type {Object.} + */ + bin = {}; + /** + * @1type {Object.} + */ + structFieldIndex = {}; + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } + } + export class OBScriptLoader { + /** + * @type {OBArrayBufferReader} + */ + reader; //OBArrayBufferReader + /** + * @type {OBArrayBufferReader} + */ + data; //OBArrayBufferReader + loadingFunctions = {}; //[OBFunctionBuilder] + Linkings = []; //Linkable + + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadUInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadUInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadUInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + let length = SegmentReader.ReadUInt32(); + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + // let typeIdx = reader.ReadUInt32(); + // let count = reader.ReadInt32(); + let vari = reader.ReadUInt32(); + let count = vari & 0xFFFFFFF; + let typeIdx = vari >> 28; + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadUInt32(); + let d = {}; + let cnt = reader.ReadUInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadUInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadUInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadUInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } + } + + export class OBArrayBufferReader { + /** + * @type {Number} integer of position + */ + pos; // int + /** + * @type {Number} integer of start + */ + start; // int + /** + * @type {ArrayBuffer} + */ + buf; // ArrayBuffer + /** + * @type DataView + */ + view; // DataView + /** + * @type {Object.} + */ + stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.start = 0; + this.view = new DataView(buf); + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(this.start + p, true); + // let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(this.start + p, true); + // let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(this.start + p, true); + // let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let str = this.stringCache[stringIdx]; + if (str) { + return str; + } + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(this.start + start, true); + if (length === 0) { + return ""; + } + start = this.start + start + 4; + // start = start + 4; + let ab = this.buf.slice(start, start + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + this.stringCache[stringIdx] = str; + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + // let buf; + // if (typeof (length) === "undefined") { + // buf = this.buf.slice(pos); + // } else { + // buf = this.buf.slice(pos, pos + length); + // } + // let reader = new OBArrayBufferReader(buf); + // reader.start = this.start + pos; + // return reader; + let reader = new OBArrayBufferReader(this.buf); + reader.start = this.start + pos; + return reader; + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } + } + + + export class OBStatementContext { + InstPos; + Actions = []; + + PushAction(Instruction) { + this.Actions.push(Instruction); + } + } + // 虚拟机 + + export class VMInterruptException { + } + export class ChangeStateException extends VMInterruptException { + } + export class ChangeDestroyException extends VMInterruptException { + } + export class OBVM { + /** + * @1type {function(any)} + */ + Output; + /** + * typeName->[VMFSM] + * @1type {Object.} + */ + Running = {}; + /** + * @type OBScript + */ + script; + /** + * @1type {OBVMFSM} + */ + Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script) { + if (!script) { + throw Error("Script is null"); + } + this.script = script; + } + + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + // let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } + } + export class OBVMFSM { + static ID_GEN = 0; + /** + * @type {any} + */ + Target; + /** + * @type {OBFSM} + */ + data; + id; + /** + * @type {OBVMState} + */ + CurrentState; + /** + * @type {OBVMState[]} + */ + StateStack = []; + /** + * @type {OBVM} + */ + VM; + Inbox = []; + PrioritizedInbox = []; + VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.data = data; + this.id = ++OBVMFSM.ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + if (!this.CurrentState) { + return; + } + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } + } + export class OBTypedVariableGroup { + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } + } + export class OBVMState { + /** + * @type {OBState} + */ + data; + /** + * @type {OBVMFSM} + */ + fsm; + /** + * @type {OBTypedVariableGroup} + */ + VariableGroup; + /** + * @type {OBMessage} + */ + currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } + } + export class OBVMFunction { + /** + * @type {OBFunction} + */ + data; + /** + * @type {OBTypedVariableGroup} + */ + LocalVar; + returnType = -1; + returnValue; + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } + } + export class OBMessage { + name; + arg; + argType; + sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } + } + export class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } + } + export class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } + } + // 字节码 + export class LDSTR extends OBInstruction { + Value; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } + } + export class PRT extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } + } + export class ReceivedMessage extends OBInstruction { + typeId; + Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } + } + export class STVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + export class STVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + export class StructFieldDesc extends OBInstruction { + fieldTypeId; + fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } + } + export class GetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + return stt.registers.LongRegister[fieldIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + export class SetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + export class CHSTT extends OBInstruction { + StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } + } + export class MethodCallRegisterInfoAnchor extends OBInstruction { + RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } + } + export class NativeMethodCall extends OBInstruction { + LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } + } + export class FSMVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + export class SLF extends OBInstruction { + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } + } + export class MethodCall extends OBInstruction { + MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } + } + export class BRIFN extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + targetOffsetBak; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffsetBak = this.targetOffset; + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } + } + export class BR extends OBInstruction { + Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } + } + export class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } + } + export class ARITHF extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } + } + + export class ARITHI extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } + } + export class LDI extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } + } + export class LDF extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFFF; + switch (specal) { + case 0xFFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } + } + export class RET extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } + } + export class FSMVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + export class CreateFSM extends OBInstruction { + FSMTypeName; + ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } + } + export class FSMSendMsg extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + export class GZ0 extends OBInstruction { + VarType; + VarIdx; + ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } + } + + export class BRIF extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } + } + export class DEC extends OBInstruction { + regType; + regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + let v = LongReg(st, uf, locals); + return v - 1; + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + let v = DoubleReg(st, uf, locals); + return v - 1; + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } + } + export class Reg2Var extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + export class Var2Reg extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + export class I2F extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } + } + export class EQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class NEQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class LT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class LTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class GT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + + export class GTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } + } + export class FSMBroadcastMsg extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + + /** + * 单元数操作 + */ + export class SGLF extends OBInstruction { + Opcode; + value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } + } + export class RAND extends OBInstruction { + Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } + } + export class F2I extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } + } + export class FSMSendMsgWait_Data extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + } + export class FSMSendMsgWait extends OBInstruction { + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } + } + export class FSMBroadcastMsgWait extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + export class TextJoin extends OBInstruction { + Left; + Right; + RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } + } + export class ToString extends OBInstruction { + ValueType; + ValueRegIdx; + RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + export class Sender extends OBInstruction { + RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } + } + export class SHL extends OBInstruction { + value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } + } + export class AND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } + } + export class FIX extends OBInstruction { + regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } + } + /** + * value of may by key + */ + export class VOM extends OBInstruction { + map; + key; + ValueType; + RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + export class LAND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } + } + export class LOR extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 1 : 0; + } + }; + } + } + export class LNOT extends OBInstruction { + a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } + } + export class COND extends OBInstruction { + if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } + } + export class NEW extends OBInstruction { + StructDef; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFF0000) >> 16; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } + } + + export class OBStructDataSerializer { + relocation = new Relocation(); + /** + * + * @param {OBStructValue[]} valueData + * @returns {int[]} + */ + serialize(valueDataArray) { + let group = this.groupData(valueDataArray); + } + /** + * + * @param {OBStructValue[]} valueDataArray + * @returns {Object. { + let list = group[d.Def.Name]; + if (!list) { + list = []; + group[d.Def.Name] = list; + } + this.collData(d); + list.push(d); + }); + return group; + } + /** + * + * @param {OBStructValue} d + */ + collData(d) { + d.string.forEach(str => { + this.relocation.addRelocationString(str); + }); + d.registers.object.forEach(ofd => { + switch (ofd.type.$__type) { + case "StructFieldTypeStruct": + break; + case "StructFieldTypeIntegerMap": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + break; + case "StructFieldTypeStringMap": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + break; + case "StructFieldTypeList": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + break; + default: + console.error(ofd); + throw Error("功能未实现 " + ofd.type.$__type); + } + }); + } + } \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/i18n/en-US.json b/hap/entry/src/main/js/MainAbility/i18n/en-US.json new file mode 100644 index 0000000..08e34ea --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/i18n/en-US.json @@ -0,0 +1,11 @@ +{ + "strings": { + "hello": "Hello", + "world": "World", + "page": "Second Page", + "next": "Next Page", + "back": "Back" + }, + "Files": { + } +} \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json b/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json new file mode 100644 index 0000000..3dd53b3 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json @@ -0,0 +1,11 @@ +{ + "strings": { + "hello": "您好", + "world": "世界", + "page": "第二页", + "next": "下一页", + "back": "返回" + }, + "Files": { + } +} \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.css b/hap/entry/src/main/js/MainAbility/pages/index/index.css new file mode 100644 index 0000000..280f036 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.css @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +@import '../../common/normalize.css'; +@import "../../common/common.css"; + diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.hml b/hap/entry/src/main/js/MainAbility/pages/index/index.hml new file mode 100644 index 0000000..f4ed250 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.hml @@ -0,0 +1,32 @@ + + +
+ + + +
+ +
+ +
\ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js new file mode 100644 index 0000000..e317d75 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2020-2021 Du Tian Wei + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import router from '@system.router'; +import fileio from '@ohos.fileio'; +import * as obvm from '../../common/runtime/vm.js'; +import * as obcanvaslib from '../../common/canvas.js' +import prompt from '@system.prompt'; + +let filepath = '/data/openblock.xe'; +export default { + data: { + info: "info:", + vm: null, + fsm: null, + uninited: true, + updateInterval: 0, + fileCheckInterval: 0, + filectime: -1, + ui: [{ + type: 'button' + }] + }, + log(s) { + this.info = s; + }, + ob_event(name) { + this.log(name); + try { + if (this.vm) { + this.log("1"); + this.vm.BroadcastMessage(new obvm.OBEventMessage(name, "", null, null)); + this.log("2"); + } + } catch (e) { + this.log(e + ""); + } + }, + ob_click(e) { + this.ob_event("click"); + }, + touchStart(e) { + this.ob_event("touchstart"); + }, + ob_touchmove(e) { + this.ob_event("touchmove"); + }, + ob_touchend(e) { + this.ob_event("touchend"); + }, + ob_longpress(e) { + this.ob_event("longpress"); + }, + ob_swipe(e) { + this.ob_event("swipe"); + }, + initStage() { + let stage = this.$refs.canvas1; + try { + stage.width = stage.width; + let fd = fileio.openSync(filepath, 0o2); + let st = fileio.fstatSync(fd); + let scriptArrayBuffer = new ArrayBuffer(st.size); + fileio.readSync(fd, scriptArrayBuffer); + + let obcanvas = new obcanvaslib.OBCanvas2D(stage); + // let ctx = stage.getContext('2d'); + // ctx.fillRect(15, 15, 50, 50); + + let nativeLibs = [obcanvas.install.bind(obcanvas)]; + let loader = obvm.OBScriptLoader; + let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); + this.vm = new obvm.OBVM(loadedScript); + // // vm.Output = alert.bind(window); + this.vm.Output = prompt.showToast; + let fsmname = 'Start.Main'; + let fsm = this.vm.CreateFSM(fsmname); + if (!fsm) { + throw Error("No FSM named " + fsmname); + } + this.fsm = fsm; + } catch (e) { + this.info = "\nERROR:" + e.toString(); + } finally { + } + }, + onActive() { + if (this.uninited) { + this.uninited = false; + this.initStage(); + } + this.updateInterval = setInterval(this.update, 30); + this.fileCheckInterval = setInterval(this.checkFile, 3000); + }, + checkFile() { + let fd = fileio.openSync(filepath, 0o2); + let stat = fileio.fstatSync(fd); + let ctime = stat.ctime; + if (this.filectime == -1) { + this.filectime = ctime; + } else if (this.filectime != ctime) { + this.filectime = ctime; + this.initStage(); + } + }, + onInactive() { + clearInterval(this.updateInterval); + clearInterval(this.fileCheckInterval); + }, + update() { + if (this.vm) { + this.vm.update(); + } + }, + onchange(type) { + router.push({ + uri: "pages/" + type + "/index" + }) + } +} diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.css b/hap/entry/src/main/js/MainAbility/pages/second/second.css new file mode 100644 index 0000000..31a3676 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.css @@ -0,0 +1,24 @@ +.container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + left: 0px; + top: 0px; + width: 100%; + height: 100%; +} + +.title { + font-size: 60px; + text-align: center; + width: 100%; + height: 40%; + margin: 10px; +} + +.btn { + width: 50%; + height: 100px; + font-size: 40px; +} diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.hml b/hap/entry/src/main/js/MainAbility/pages/second/second.hml new file mode 100644 index 0000000..d75ce93 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.hml @@ -0,0 +1,6 @@ +
+ + {{ $t('strings.page') }} + + +
diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.js b/hap/entry/src/main/js/MainAbility/pages/second/second.js new file mode 100644 index 0000000..ac4f4f8 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.js @@ -0,0 +1,12 @@ +import router from '@system.router' + +export default { + data: { + title: 'World' + }, + onclick: function () { + router.replace({ + uri: "pages/index/index" + }) + } +} diff --git a/hap/entry/src/main/resources/base/element/string.json b/hap/entry/src/main/resources/base/element/string.json index d3882f9..8dab0f2 100644 --- a/hap/entry/src/main/resources/base/element/string.json +++ b/hap/entry/src/main/resources/base/element/string.json @@ -1,12 +1,12 @@ { "string": [ { - "name": "app_name", + "name": "entry_MainAbility", "value": "OpenBlock" }, { - "name": "mainability_description", - "value": "JS_Phone_Empty Feature Ability" + "name": "description_mainability", + "value": "OpenBlock Ability" } ] } \ No newline at end of file diff --git a/hap/gradle.properties b/hap/gradle.properties new file mode 100644 index 0000000..be49249 --- /dev/null +++ b/hap/gradle.properties @@ -0,0 +1,13 @@ +# Project-wide Gradle settings. +# IDE (e.g. DevEco Studio) users: +# Gradle settings configured through the IDE *will override* +# any settings specified in this file. +# For more details on how to configure your build environment visit +# http://www.gradle.org/docs/current/userguide/build_environment.html +# Specifies the JVM arguments used for the daemon process. +# The setting is particularly useful for tweaking memory settings. +# If the Chinese output is garbled, please configure the following parameter. +# This function is enabled by default when the DevEco Studio builds the hap/app,if you need disable gradle parallel,you should set org.gradle.parallel false. +# more information see https://docs.gradle.org/current/userguide/performance.html +# org.gradle.parallel=false +# org.gradle.jvmargs=-Dfile.encoding=GBK \ No newline at end of file diff --git a/hap/gradle/wrapper/gradle-wrapper.jar b/hap/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000000000000000000000000000000000000..490fda8577df6c95960ba7077c43220e5bb2c0d9 GIT binary patch literal 58694 zcma&OV~}Oh(k5J8>Mq;1ZQHhO+v>7y+qO>Gc6Hgdjp>5?}0s%q%y~>Cv3(!c&iqe4q$^V<9O+7CU z|6d2bzlQvOI?4#hN{EUmDbvb`-pfo*NK4Vs&cR60P)<+IG%C_BGVL7RP11}?Ovy}9 zNl^cQJPR>SIVjSkXhS0@IVhqGLL)&%E<(L^ymkEXU!M5)A^-c;K>yy`Ihy@nZ}orr zK>gFl%+bKu+T{P~iuCWUZjJ`__9l-1*OFwCg_8CkKtLEEKtOc=d5NH%owJkk-}N#E z7Pd;x29C}qj>HVKM%D&SPSJ`JwhR2oJPU0u3?)GiA|6TndJ+~^eXL<%D)IcZ)QT?t zE7BJP>Ejq;`w$<dd^@|esR(;1Z@9EVR%7cZG`%Xr%6 zLHXY#GmPV!HIO3@j5yf7D{PN5E6tHni4mC;qIq0Fj_fE~F1XBdnzZIRlk<~?V{-Uc zt9ldgjf)@8NoAK$6OR|2is_g&pSrDGlQS);>YwV7C!=#zDSwF}{_1#LA*~RGwALm) zC^N1ir5_}+4!)@;uj92irB5_Ugihk&Uh|VHd924V{MiY7NySDh z|6TZCb1g`c)w{MWlMFM5NK@xF)M33F$ZElj@}kMu$icMyba8UlNQ86~I$sau*1pzZ z4P)NF@3(jN(thO5jwkx(M5HOe)%P1~F!hXMr%Rp$&OY0X{l_froFdbi(jCNHbHj#! z(G`_tuGxu#h@C9HlIQ8BV4>%8eN=MApyiPE0B3dR`bsa1=MM$lp+38RN4~`m>PkE? zARywuzZ#nV|0wt;22|ITkkrt>ahz7`sKXd2!vpFCC4i9VnpNvmqseE%XnxofI*-Mr6tjm7-3$I-v}hr6B($ALZ=#Q4|_2l#i5JyVQCE{hJAnFhZF>vfSZgnw`Vgn zIi{y#1e7`}xydrUAdXQ%e?_V6K(DK89yBJ;6Sf{Viv*GzER9C3Mns=nTFt6`Eu?yu<*Fb}WpP$iO#-y+^H>OQ< zw%DSM@I=@a)183hx!sz(#&cg-6HVfK(UMgo8l2jynx5RWEo8`?+^3x0sEoj9H8%m1 z87?l+w;0=@Dx_J86rA6vesuDQ^nY(n?SUdaY}V)$Tvr%>m9XV>G>6qxKxkH zN6|PyTD(7+fjtb}cgW1rctvZQR!3wX2S|ils!b%(=jj6lLdx#rjQ6XuJE1JhNqzXO zKqFyP8Y1tN91g;ahYsvdGsfyUQz6$HMat!7N1mHzYtN3AcB>par(Q>mP7^`@7@Ox14gD12*4RISSYw-L>xO#HTRgM)eLaOOFuN}_UZymIhu%J?D|k>Y`@ zYxTvA;=QLhu@;%L6;Ir_$g+v3;LSm8e3sB;>pI5QG z{Vl6P-+69G-P$YH-yr^3cFga;`e4NUYzdQy6vd|9${^b#WDUtxoNe;FCcl5J7k*KC z7JS{rQ1%=7o8to#i-`FD3C?X3!60lDq4CqOJ8%iRrg=&2(}Q95QpU_q ziM346!4()C$dHU@LtBmfKr!gZGrZzO{`dm%w_L1DtKvh8UY zTP3-|50~Xjdu9c%Cm!BN^&9r?*Wgd(L@E!}M!#`C&rh&c2fsGJ_f)XcFg~$#3S&Qe z_%R=Gd`59Qicu`W5YXk>vz5!qmn`G>OCg>ZfGGuI5;yQW9Kg*exE+tdArtUQfZ&kO ze{h37fsXuQA2Z(QW|un!G2Xj&Qwsk6FBRWh;mfDsZ-$-!YefG!(+bY#l3gFuj)OHV830Xl*NKp1-L&NPA3a8jx#yEn3>wea~ z9zp8G6apWn$0s)Pa!TJo(?lHBT1U4L>82jifhXlkv^a+p%a{Og8D?k6izWyhv`6prd7Yq5{AqtzA8n{?H|LeQFqn(+fiIbDG zg_E<1t%>753QV!erV^G4^7p1SE7SzIqBwa{%kLHzP{|6_rlM*ae{*y4WO?{%&eQ`| z>&}ZkQ;<)rw;d(Dw*om?J@3<~UrXsvW2*0YOq_-Lfq45PQGUVu?Ws3&6g$q+q{mx4 z$2s@!*|A+74>QNlK!D%R(u22>Jeu}`5dsv9q~VD!>?V86x;Fg4W<^I;;ZEq5z4W5c z#xMX=!iYaaW~O<(q>kvxdjNk15H#p0CSmMaZB$+%v90@w(}o$T7;(B+Zv%msQvjnW z`k7=uf(h=gkivBw?57m%k^SPxZnYu@^F% zKd`b)S#no`JLULZCFuP^y5ViChc;^3Wz#c|ehD+2MHbUuB3IH5+bJ_FChTdARM6Q2 zdyuu9eX{WwRasK!aRXE+0j zbTS8wg@ue{fvJ*=KtlWbrXl8YP88;GXto?_h2t@dY3F?=gX9Frwb8f1n!^xdOFDL7 zbddq6he>%k+5?s}sy?~Ya!=BnwSDWloNT;~UF4|1>rUY!SSl^*F6NRs_DT-rn=t-p z_Ga0p)`@!^cxW_DhPA=0O;88pCT*G9YL29_4fJ(b{| zuR~VCZZCR97e%B(_F5^5Eifes$8!7DCO_4(x)XZDGO%dY9Pkm~-b1-jF#2H4kfl<3 zsBes0sP@Zyon~Q&#<7%gxK{o+vAsIR>gOm$w+{VY8ul7OsSQ>07{|7jB6zyyeu+WU zME>m2s|$xvdsY^K%~nZ^%Y`D7^PCO(&)eV-Qw|2_PnL=Nd=}#4kY)PS=Y62Dzz1e2 z&*)`$OEBuC&M5f`I}A-pEzy^lyEEcd$n1mEgLj}u_b^d!5pg{v+>_FexoDxYj%X_F z5?4eHVXurS%&n2ISv2&Eik?@3ry}0qCwS9}N)`Zc_Q8}^SOViB_AB&o6Eh#bG;NnL zAhP2ZF_la`=dZv6Hs@78DfMjy*KMSExRZfccK=-DPGkqtCK%U1cUXxbTX-I0m~x$3 z&Oc&aIGWtcf|i~=mPvR^u6^&kCj|>axShGlPG}r{DyFp(Fu;SAYJ}9JfF*x0k zA@C(i5ZM*(STcccXkpV$=TznZKQVtec!A24VWu*oS0L(^tkEm2ZIaE4~~?#y9Z4 zlU!AB6?yc(jiB`3+{FC zl|IdP1Fdt#e5DI{W{d8^$EijTU(8FA@8V&_A*tO?!9rI zhoRk`Q*riCozP>F%4pDPmA>R#Zm>_mAHB~Y5$sE4!+|=qK0dhMi4~`<6sFHb=x8Naml}1*8}K_Es3#oh3-7@0W}BJDREnwWmw<{wY9p)3+Mq2CLcX?uAvItguqhk*Po!RoP`kR)!OQy3Ayi zL@ozJ!I_F2!pTC?OBAaOrJmpGX^O(dSR-yu5Wh)f+o5O262f6JOWuXiJS_Jxgl@lS z6A9c*FSHGP4HuwS)6j3~b}t{+B(dqG&)Y}C;wnb!j#S0)CEpARwcF4Q-5J1NVizx7 z(bMG>ipLI1lCq?UH~V#i3HV9|bw%XdZ3Q#c3)GB+{2$zoMAev~Y~(|6Ae z^QU~3v#*S>oV*SKvA0QBA#xmq9=IVdwSO=m=4Krrlw>6t;Szk}sJ+#7=ZtX(gMbrz zNgv}8GoZ&$=ZYiI2d?HnNNGmr)3I);U4ha+6uY%DpeufsPbrea>v!D50Q)k2vM=aF-zUsW*aGLS`^2&YbchmKO=~eX@k9B!r;d{G% zrJU~03(->>utR^5;q!i>dAt)DdR!;<9f{o@y2f}(z(e)jj^*pcd%MN{5{J=K<@T!z zseP#j^E2G31piu$O@3kGQ{9>Qd;$6rr1>t!{2CuT_XWWDRfp7KykI?kXz^{u_T2AZ z-@;kGj8Iy>lOcUyjQqK!1OHkY?0Kz+_`V8$Q-V|8$9jR|%Ng;@c%kF_!rE3w>@FtX zX1w7WkFl%Vg<mE0aAHX==DLjyxlfA}H|LVh;}qcWPd8pSE!_IUJLeGAW#ZJ?W}V7P zpVeo|`)a<#+gd}dH%l)YUA-n_Vq3*FjG1}6mE;@A5ailjH*lJaEJl*51J0)Xecn6X zz zDr~lx5`!ZJ`=>>Xb$}p-!3w;ZHtu zX@xB4PbX!J(Jl((<8K%)inh!-3o2S2sbI4%wu9-4ksI2%e=uS?Wf^Tp%(Xc&wD6lV z*DV()$lAR&##AVg__A=Zlu(o$3KE|N7ZN{X8oJhG+FYyF!(%&R@5lpCP%A|{Q1cdr>x0<+;T`^onat<6tlGfEwRR?ZgMTD-H zjWY?{Fd8=Fa6&d@0+pW9nBt-!muY@I9R>eD5nEDcU~uHUT04gH-zYB>Re+h4EX|IH zp`Ls>YJkwWD3+}DE4rC3kT-xE89^K@HsCt6-d;w*o8xIHua~||4orJ<7@4w_#C6>W z2X$&H38OoW8Y-*i=@j*yn49#_C3?@G2CLiJUDzl(6P&v`lW|=gQ&)DVrrx8Bi8I|$ z7(7`p=^Lvkz`=Cwd<0%_jn&6k_a(+@)G^D04}UylQax*l(bhJ~;SkAR2q*4>ND5nc zq*k9(R}Ijc1J8ab>%Tv{kb-4TouWfA?-r(ns#ghDW^izG3{ts{C7vHc5Mv?G;)|uX zk&Fo*xoN`OG9ZXc>9(`lpHWj~9!hI;2aa_n!Ms1i;BFHx6DS23u^D^e(Esh~H@&f}y z(=+*7I@cUGi`U{tbSUcSLK`S)VzusqEY)E$ZOokTEf2RGchpmTva?Fj! z<7{9Gt=LM|*h&PWv6Q$Td!|H`q-aMIgR&X*;kUHfv^D|AE4OcSZUQ|1imQ!A$W)pJtk z56G;0w?&iaNV@U9;X5?ZW>qP-{h@HJMt;+=PbU7_w`{R_fX>X%vnR&Zy1Q-A=7**t zTve2IO>eEKt(CHjSI7HQ(>L5B5{~lPm91fnR^dEyxsVI-wF@82$~FD@aMT%$`usqNI=ZzH0)u>@_9{U!3CDDC#xA$pYqK4r~9cc_T@$nF1yODjb{=(x^({EuO?djG1Hjb{u zm*mDO(e-o|v2tgXdy87*&xVpO-z_q)f0~-cf!)nb@t_uCict?p-L%v$_mzG`FafIV zPTvXK4l3T8wAde%otZhyiEVVU^5vF zQSR{4him-GCc-(U;tIi;qz1|Az0<4+yh6xFtqB-2%0@ z&=d_5y>5s^NQKAWu@U#IY_*&G73!iPmFkWxxEU7f9<9wnOVvSuOeQ3&&HR<>$!b%J z#8i?CuHx%la$}8}7F5-*m)iU{a7!}-m@#O}ntat&#d4eSrT1%7>Z?A-i^Y!Wi|(we z$PBfV#FtNZG8N-Ot#Y>IW@GtOfzNuAxd1%=it zDRV-dU|LP#v70b5w~fm_gPT6THi zNnEw&|Yc9u5lzTVMAL} zgj|!L&v}W(2*U^u^+-e?Tw#UiCZc2omzhOf{tJX*;i2=i=9!kS&zQN_hKQ|u7_3vo6MU0{U+h~` zckXGO+XK9{1w3Z$U%%Fw`lr7kK8PzU=8%0O8ZkW`aQLFlR4OCb^aQgGCBqu6AymXk zX!p(JDJtR`xB$j48h}&I2FJ*^LFJzJQJ0T>=z{*> zWesZ#%W?fm`?f^B^%o~Jzm|Km5$LP#d7j9a{NCv!j14axHvO<2CpidW=|o4^a|l+- zSQunLj;${`o%xrlcaXzOKp>nU)`m{LuUW!CXzbyvn;MeK#-D{Z4)+>xSC)km=&K%R zsXs3uRkta6-rggb8TyRPnquv1>wDd)C^9iN(5&CEaV9yAt zM+V+%KXhGDc1+N$UNlgofj8+aM*(F7U3=?grj%;Pd+p)U9}P3ZN`}g3`{N`bm;B(n z12q1D7}$``YQC7EOed!n5Dyj4yl~s0lptb+#IEj|!RMbC!khpBx!H-Kul(_&-Z^OS zQTSJA@LK!h^~LG@`D}sMr2VU#6K5Q?wqb7-`ct2(IirhhvXj?(?WhcNjJiPSrwL0} z8LY~0+&7<~&)J!`T>YQgy-rcn_nf+LjKGy+w+`C*L97KMD%0FWRl`y*piJz2=w=pj zxAHHdkk9d1!t#bh8Joi1hTQr#iOmt8v`N--j%JaO`oqV^tdSlzr#3 zw70~p)P8lk<4pH{_x$^i#=~E_ApdX6JpR`h{@<Y;PC#{0uBTe z1Puhl^q=DuaW}Gdak6kV5w);35im0PJ0F)Zur)CI*LXZxZQTh=4dWX}V}7mD#oMAn zbxKB7lai}G8C){LS`hn>?4eZFaEw-JoHI@K3RbP_kR{5eyuwBL_dpWR>#bo!n~DvoXvX`ZK5r|$dBp6%z$H@WZ6Pdp&(zFKGQ z2s6#ReU0WxOLti@WW7auSuyOHvVqjaD?kX;l)J8tj7XM}lmLxLvp5V|CPQrt6ep+t z>7uK|fFYALj>J%ou!I+LR-l9`z3-3+92j2G`ZQPf18rst;qXuDk-J!kLB?0_=O}*XQ5wZMn+?ZaL5MKlZie- z0aZ$*5~FFU*qGs|-}v-t5c_o-ReR@faw^*mjbMK$lzHSheO*VJY)tBVymS^5ol=ea z)W#2z8xCoh1{FGtJA+01Hwg-bx`M$L9Ex-xpy?w-lF8e*xJXS4(I^=k1zFy|V)=ll z#&yez3hRC5?@rPywJo2eOHWezUxZphm#wo`oyA-sP@|^+LV0^nzq|UJEZZM9wqa z5Y}M0Lu@0Qd%+Q=3kCSb6q4J60t_s(V|qRw^LC>UL7I`=EZ zvIO;P2n27=QJ1u;C+X)Si-P#WB#phpY3XOzK(3nEUF7ie$>sBEM3=hq+x<=giJjgS zo;Cr5uINL%4k@)X%+3xvx$Y09(?<6*BFId+399%SC)d# zk;Qp$I}Yiytxm^3rOxjmRZ@ws;VRY?6Bo&oWewe2i9Kqr1zE9AM@6+=Y|L_N^HrlT zAtfnP-P8>AF{f>iYuKV%qL81zOkq3nc!_?K7R3p$fqJ?};QPz6@V8wnGX>3%U%$m2 zdZv|X+%cD<`OLtC<>=ty&o{n-xfXae2~M-euITZY#X@O}bkw#~FMKb5vG?`!j4R_X%$ZSdwW zUA0Gy&Q_mL5zkhAadfCo(yAw1T@}MNo>`3Dwou#CMu#xQKY6Z+9H+P|!nLI;4r9@k zn~I*^*4aA(4y^5tLD+8eX;UJW;>L%RZZUBo(bc{)BDM!>l%t?jm~}eCH?OOF%ak8# z*t$YllfyBeT(9=OcEH(SHw88EOH0L1Ad%-Q`N?nqM)<`&nNrp>iEY_T%M6&U>EAv3 zMsvg1E#a__!V1E|ZuY!oIS2BOo=CCwK1oaCp#1ED_}FGP(~Xp*P5Gu(Pry_U zm{t$qF^G^0JBYrbFzPZkQ;#A63o%iwe;VR?*J^GgWxhdj|tj`^@i@R+vqQWt~^ z-dLl-Ip4D{U<;YiFjr5OUU8X^=i35CYi#j7R! zI*9do!LQrEr^g;nF`us=oR2n9ei?Gf5HRr&(G380EO+L6zJD)+aTh_<9)I^{LjLZ} z{5Jw5vHzucQ*knJ6t}Z6k+!q5a{DB-(bcN*)y?Sfete7Y}R9Lo2M|#nIDsYc({XfB!7_Db0Z99yE8PO6EzLcJGBlHe(7Q{uv zlBy7LR||NEx|QyM9N>>7{Btifb9TAq5pHQpw?LRe+n2FV<(8`=R}8{6YnASBj8x}i zYx*enFXBG6t+tmqHv!u~OC2nNWGK0K3{9zRJ(umqvwQ~VvD;nj;ihior5N$Hf@y0G z$7zrb=CbhyXSy`!vcXK-T}kisTgI$8vjbuCSe7Ev*jOqI&Pt@bOEf>WoQ!A?`UlO5 zSLDKE(-mN4a{PUu$QdGbfiC)pA}phS|A1DE(f<{Dp4kIB_1mKQ5!0fdA-K0h#_ z{qMsj@t^!n0Lq%)h3rJizin0wT_+9K>&u0%?LWm<{e4V8W$zZ1w&-v}y zY<6F2$6Xk>9v{0@K&s(jkU9B=OgZI(LyZSF)*KtvI~a5BKr_FXctaVNLD0NIIokM}S}-mCB^^Sgqo%e{4!Hp)$^S%q@ zU%d&|hkGHUKO2R6V??lfWCWOdWk74WI`xmM5fDh+hy6>+e)rG_w>_P^^G!$hSnRFy z5fMJx^0LAAgO5*2-rsN)qx$MYzi<_A=|xez#rsT9&K*RCblT2FLJvb?Uv3q^@Dg+J zQX_NaZza4dAajS!khuvt_^1dZzOZ@eLg~t02)m2+CSD=}YAaS^Y9S`iR@UcHE%+L0 zOMR~6r?0Xv#X8)cU0tpbe+kQ;ls=ZUIe2NsxqZFJQj87#g@YO%a1*^ zJZ+`ah#*3dVYZdeNNnm8=XOOc<_l-b*uh zJR8{yQJ#-FyZ!7yNxY|?GlLse1ePK!VVPytKmBwlJdG-bgTYW$3T5KinRY#^Cyu@& zd7+|b@-AC67VEHufv=r5(%_#WwEIKjZ<$JD%4!oi1XH65r$LH#nHHab{9}kwrjtf= zD}rEC65~TXt=5bg*UFLw34&*pE_(Cw2EL5Zl2i^!+*Vx+kbkT_&WhOSRB#8RInsh4 z#1MLczJE+GAHR^>8hf#zC{pJfZ>6^uGn6@eIxmZ6g_nHEjMUUfXbTH1ZgT7?La;~e zs3(&$@4FmUVw3n033!1+c9dvs&5g#a;ehO(-Z}aF{HqygqtHf=>raoWK9h7z)|DUJ zlE0#|EkzOcrAqUZF+Wd@4$y>^0eh!m{y@qv6=C zD(){00vE=5FU@Fs_KEpaAU1#$zpPJGyi0!aXI8jWaDeTW=B?*No-vfv=>`L`LDp$C zr4*vgJ5D2Scl{+M;M(#9w_7ep3HY#do?!r0{nHPd3x=;3j^*PQpXv<~Ozd9iWWlY_ zVtFYzhA<4@zzoWV-~in%6$}Hn$N;>o1-pMK+w$LaN1wA95mMI&Q6ayQO9 zTq&j)LJm4xXjRCse?rMnbm%7E#%zk!EQiZwt6gMD=U6A0&qXp%yMa(+C~^(OtJ8dH z%G1mS)K9xV9dlK>%`(o6dKK>DV07o46tBJfVxkIz#%VIv{;|)?#_}Qq(&| zd&;iIJt$|`te=bIHMpF1DJMzXKZp#7Fw5Q0MQe@;_@g$+ELRfh-UWeYy%L*A@SO^J zLlE}MRZt(zOi6yo!);4@-`i~q5OUAsac^;RpULJD(^bTLt9H{0a6nh0<)D6NS7jfB ze{x#X2FLD2deI8!#U@5$i}Wf}MzK&6lSkFy1m2c~J?s=!m}7%3UPXH_+2MnKNY)cI z(bLGQD4ju@^<+%T5O`#77fmRYxbs(7bTrFr=T@hEUIz1t#*ntFLGOz)B`J&3WQa&N zPEYQ;fDRC-nY4KN`8gp*uO@rMqDG6=_hHIX#u{TNpjYRJ9ALCl!f%ew7HeprH_I2L z6;f}G90}1x9QfwY*hxe&*o-^J#qQ6Ry%2rn=9G3*B@86`$Pk1`4Rb~}`P-8^V-x+s zB}Ne8)A3Ex29IIF2G8dGEkK^+^0PK36l3ImaSv1$@e=qklBmy~7>5IxwCD9{RFp%q ziejFT(-C>MdzgQK9#gC?iFYy~bjDcFA^%dwfTyVCk zuralB)EkA)*^8ZQd8T!ofh-tRQ#&mWFo|Y3taDm8(0=KK>xke#KPn8yLCXwq zc*)>?gGKvSK(}m0p4uL8oQ~!xRqzDRo(?wvwk^#Khr&lf9YEPLGwiZjwbu*p+mkWPmhoh0Fb(mhJEKXl+d68b6%U{E994D z3$NC=-avSg7s{si#CmtfGxsijK_oO7^V`s{?x=BsJkUR4=?e@9# z-u?V8GyQp-ANr%JpYO;3gxWS?0}zLmnTgC66NOqtf*p_09~M-|Xk6ss7$w#kdP8`n zH%UdedsMuEeS8Fq0RfN}Wz(IW%D%Tp)9owlGyx#i8YZYsxWimQ>^4ikb-?S+G;HDT zN4q1{0@|^k_h_VFRCBtku@wMa*bIQc%sKe0{X@5LceE`Uqqu7E9i9z-r}N2ypvdX1{P$*-pa$A8*~d0e5AYkh_aF|LHt7qOX>#d3QOp-iEO7Kq;+}w zb)Le}C#pfmSYYGnq$Qi4!R&T{OREvbk_;7 zHP<*B$~Qij1!9Me!@^GJE-icH=set0fF-#u5Z{JmNLny=S*9dbnU@H?OCXAr7nHQH zw?$mVH^W-Y89?MZo5&q{C2*lq}sj&-3@*&EZaAtpxiLU==S@m_PJ6boIC9+8fKz@hUDw==nNm9? z`#!-+AtyCOSDPZA)zYeB|EQ)nBq6!QI66xq*PBI~_;`fHEOor}>5jj^BQ;|-qS5}1 zRezNBpWm1bXrPw3VC_VHd z$B06#uyUhx)%6RkK2r8*_LZ3>-t5tG8Q?LU0Yy+>76dD(m|zCJ>)}9AB>y{*ftDP3 z(u8DDZd(m;TcxW-w$(vq7bL&s#U_bsIm67w{1n|y{k9Ei8Q9*8E^W0Jr@M?kBFJE< zR7Pu}#3rND;*ulO8X%sX>8ei7$^z&ZH45(C#SbEXrr3T~e`uhVobV2-@p5g9Of%!f z6?{|Pt*jW^oV0IV7V76Pd>Pcw5%?;s&<7xelwDKHz(KgGL7GL?IZO%upB+GMgBd3ReR9BS zL_FPE2>LuGcN#%&=eWWe;P=ylS9oIWY)Xu2dhNe6piyHMI#X4BFtk}C9v?B3V+zty zLFqiPB1!E%%mzSFV+n<(Rc*VbvZr)iJHu(HabSA_YxGNzh zN~O(jLq9bX41v{5C8%l%1BRh%NDH7Vx~8nuy;uCeXKo2Do{MzWQyblZsWdk>k0F~t z`~8{PWc86VJ)FDpj!nu))QgHjl7a%ArDrm#3heEHn|;W>xYCocNAqX{J(tD!)~rWu zlRPZ3i5sW;k^^%0SkgV4lypb zqKU2~tqa+!Z<)!?;*50pT&!3xJ7=7^xOO0_FGFw8ZSWlE!BYS2|hqhQT8#x zm2a$OL>CiGV&3;5-sXp>3+g+|p2NdJO>bCRs-qR(EiT&g4v@yhz(N5cU9UibBQ8wM z0gwd4VHEs(Mm@RP(Zi4$LNsH1IhR}R7c9Wd$?_+)r5@aj+!=1-`fU(vr5 z1c+GqAUKulljmu#ig5^SF#{ag10PEzO>6fMjOFM_Le>aUbw>xES_Ow|#~N%FoD{5!xir^;`L1kSb+I^f z?rJ0FZugo~sm)@2rP_8p$_*&{GcA4YyWT=!uriu+ZJ%~_OD4N%!DEtk9SCh+A!w=< z3af%$60rM%vdi%^X2mSb)ae>sk&DI_&+guIC88_Gq|I1_7q#}`9b8X zGj%idjshYiq&AuXp%CXk>zQ3d2Ce9%-?0jr%6-sX3J{*Rgrnj=nJ2`#m`TaW-13kl zS2>w8ehkYEx@ml2JPivxp zIa2l^?)!?Y*=-+jk_t;IMABQ5Uynh&LM^(QB{&VrD7^=pXNowzD9wtMkH_;`H|d0V z*rohM)wDg^EH_&~=1j1*?@~WvMG3lH=m#Btz?6d9$E*V5t~weSf4L%|H?z-^g>Fg` zI_Q+vgHOuz31?mB{v#4(aIP}^+RYU}^%XN}vX_KN=fc{lHc5;0^F2$2A+%}D=gk-) zi1qBh!1%xw*uL=ZzYWm-#W4PV(?-=hNF%1cXpWQ_m=ck1vUdTUs5d@2Jm zV8cXsVsu~*f6=_7@=1 zaV0n2`FeQ{62GMaozYS)v~i10wGoOs+Z8=g$F-6HH1qBbasAkkcZj-}MVz{%xf8`2 z1XJU;&QUY4Hf-I(AG8bX zhu~KqL}TXS6{)DhW=GFkCzMFMSf`Y00e{Gzu2wiS4zB|PczU^tjLhOJUv=i2KuFZHf-&`wi>CU0h_HUxCdaZ`s9J8|7F}9fZXg`UUL}ws7G=*n zImEd-k@tEXU?iKG#2I13*%OX#dXKTUuv1X3{*WEJS41ci+uy=>30LWCv*YfX_A2(M z9lnNAjLIzX=z;g;-=ARa<`z$x)$PYig1|#G;lnOs8-&rB2lT0#e;`EH8qZ_xNvwy7 zo_9>P@SHK(YPu*8r86f==eshYjM3yAPOHDn- zmuW04o02AGMz!S|S32(h560d(IP$;S7LIM(PC7Owwr$&XCbsQNY))+3HYS+ZcHTVq zJm;QsfA`#~_m8fwuI~DFb$@pE-h1t}*HZB7hc-CUM~x6aZ<4v9_Jr-))=El>(rphK z(@wMC$e>^o+cQ(9S+>&JfP;&KM6nff2{RNu;MqE9>L9t^lvzo^*B5>@$TG!gZlh0Z z%us8ys$1~v&&N-gPBvXl5b<#>-@lhAkg_4Ev6#R&r{ObIn=Qki&`wxR_OWj%kU_RW&w#Mxv%x zW|-sJ^jss+;xmxi8?gphNW{^HZ!xF?poe%mgZ>nwlqgvH@TrZ zad5)yJx3T|&$Afl$pkh=7bZAwBdv+tQEP=d3vE#o<&r6h+sTU$64ZZQ0e^Fu9FrnL zN-?**4ta&!+{cP=jt`w)5|dD&CP@-&*BsN#mlbUn!V*(E_gskcQ*%F#Nw#aTkp%x| z8^&g)1d!%Y+`L!Se2s_XzKfonT_BWbn}LQo#YUAx%f7L__h4Xi680GIk)s z8GHm59EYn(@4c&eAO)}0US@((t#0+rNZ680SS<=I^|Y=Yv)b<@n%L20qu7N%V1-k1 z*oxpOj$ZAc>L6T)SZX?Pyr#}Q?B`7ZlBrE1fHHx_Au{q9@ zLxwPOf>*Gtfv6-GYOcT^ZJ7RGEJTVXN=5(;{;{xAV3n`q1Z-USkK626;atcu%dTHU zBewQwrpcZkKoR(iF;fVev&D;m9q)URqvKP*eF9J=A?~0=jn3=_&80vhfBp?6@KUpgyS`kBk(S0@X5Xf%a~?#4Ct5nMB9q~)LP<`G#T-eA z+)6cl1H-2uMP=u<=saDj*;pOggb2(NJO^pW8O<6u^?*eiqn7h)w9{D`TrE1~k?Xuo z(r%NIhw3kcTHS%9nbff>-jK1k^~zr8kypQJ6W+?dkY7YS`Nm z5i;Q23ZpJw(F7|e?)Tm~1bL9IUKx6GC*JpUa_Y00Xs5nyxGmS~b{ zR!(TzwMuC%bB8&O->J82?@C|9V)#i3Aziv7?3Z5}d|0eTTLj*W3?I32?02>Eg=#{> zpAO;KQmA}fx?}j`@@DX-pp6{-YkYY81dkYQ(_B88^-J#rKVh8Wys-;z)LlPu{B)0m zeZr=9{@6=7mrjShh~-=rU}n&B%a7qs1JL_nBa>kJFQ8elV=2!WY1B5t2M5GD5lt|f zSAvTgLUv#8^>CX}cM(i(>(-)dxz;iDvWw5O!)c5)TBoWp3$>3rUI=pH9D1ffeIOUW zDbYx}+)$*+`hT}j226{;=*3(uc*ge(HQpTHM4iD&r<=JVc1(gCy}hK%<(6)^`uY4>Tj6rIHYB zqW5UAzpdS!34#jL;{)Fw{QUgJ~=w`e>PHMsnS1TcIXXHZ&3M~eK5l>Xu zKsoFCd%;X@qk#m-fefH;((&?Y9grF{Al#55A3~L5YF0plJ;G=;Tr^+W-7|6IO;Q+8 z(jAXq$ayf;ZkMZ4(*w?Oh@p8LhC6=8??!%@V(e}%*>fW^Gdn|qZVyvHhcn;7nP7e; z13!D$^-?^#x*6d1)88ft06hVZh%m4w`xR?!cnzuoOj(g9mdE2vbKT@RghJ)XOPj{9 z@)8!#=HRJvG=jDJ77XND;cYsC=CszC!<6GUC=XLuTJ&-QRa~EvJ1rk2+G!*oQJ-rv zDyHVZ{iQN$*5is?dNbqV8|qhc*O15)HGG)f2t9s^Qf|=^iI?0K-Y1iTdr3g=GJp?V z$xZiigo(pndUv;n1xV1r5+5qPf#vQQWw3m&pRT>G&vF( zUfKIQg9%G;R`*OdO#O;nP4o+BElMgmKt<>DmKO1)S$&&!q6#4HnU4||lxfMa-543{ zkyJ+ohEfq{OG3{kZszURE;Rw$%Q;egRKJ%zsVcXx!KIO0*3MFBx83sD=dDVsvc17i zIOZuEaaI~q`@!AR{gEL#Iw}zQpS$K6i&omY2n94@a^sD@tQSO(dA(npgkPs7kGm>;j?$Ia@Q-Xnzz?(tgpkA6VBPNX zE?K%$+e~B{@o>S+P?h6K=XP;caQ=3)I{@ZMNDz)9J2T#5m#h9nXd*33TEH^v7|~i) zeYctF*06eX)*0e{xXaPT!my1$Xq>KPJakJto3xnuT&z zSaL8NwRUFm?&xIMwA~gt4hc3=hAde#vDjQ!I)@;V<9h2YOvi-XzleP!g4blZm|$iV zF%c3G8Cs;FH8|zEczqGSY%F54h`$P_VsmJ6TaXRLc8lSf`Sv%s%6<4+;Wbs-3lya( z=9I>I%97Y~G945O48YaAq6ENPUs%EJvyC! zM4jMgJj}r~@D;cdaQ-j#`5zCRku}42aI<>CgraXuKDr19db~#|@UyM;f-uc!(KDsu z5EA@CsN>^t@oH+0!SALi;ud>`P5mQta+Lh*-#RHJ)Gin%>EaFLSoU`(TG7c|yeFvl zk|Yll%)h-*%WoI6M*j+4xw`OqiDVX{k-^V2{rzCIM9mzNHGP^D={!*P7T)%yDSI5- zkGA4}r3`)#Vl6JFJ3xG)8K;FTtII9o7jNHof_Z_Zc<%@-H4RPpyXudpf)ky zmTH$LFGxaIUGQ;l=>R>?+>ZSCU|@&+Gt@5Bj3w{L{KPpgQ<~)jqx0oNZSv9R&^A42 zzqJr?C#D-n>=9FjM=D=7h_$QO$KQ8*%0%)rI(Npai_JjE9_lBk75BQMI zkk4X5PATWgrub!fb5Hxi8{(Y<(GOO8^HECOA)eanyS{u%leQOkp;1W}_8eH?nPQxW zd#Z+uJfTK>g-TR3WPu~2Ru9A+NkuIICM@PyPmJn(GBZt;xFZNDMbw8`xzl2`(?UC- z#<*=*fo{UOvycb|b&4y0Nm!sHhFMI*Y$Olgh;BG#xBU+yxav82Ejj(ZvQ|64Wwy7I zN=DXx7(V^NTH3YRB4HOu6T5=DW86P`L#Ng!SuT{%&>Cq8>|o8lF^^U%MRU41TT?h& z!uJ$YdbM*2y?#`LJ2)XPoKq`hm$I3R{V5-;@u7!E9tH4sR(`Ab-Qh!|UN-a5fZ?P@2LWRvSv!hOk08;Yy!h&uEI-X}j+&v`X` zkqY%*F@{}DHL*Jgjg2}a54hwEV`63bK4>mL%D^YT|>m1-kX{876BRm&`Y#{$&oz($qWJL}T*tj42k+yu8fa=4b7VUPq()Wb~=L?DU0U-4*Iu^KMZBRByWn-@=_f(4){Or#| zpw}~Ajs6a=z!8_H59lqYlfnS77QY0pHpIz0#)}!EGhypupZeZe@%cv z6Dngnl*SsUy^a`v?>lARi6Yps@%32JpGQvrcd*A8LPLEInBEU2vriGvMqG!jh^=Gj zXvu5zpikqnt*e4&Un_e$2FAB?(yOS0JAzxh@nN?Blqc-)Pv`U}&E5|# z)97-9utpqi*`hR+$;eS)A+KK)CO)V`b?*}z&*+28mDfWI31)sF)tBg6LVlxS z225poL+O|x)5;skkj{rew<}TsDVqFMMLSgd;UK7^clMcObM~IgSq6!eJ($JP!KHPr zBJ&SHi{wLsgMzn1^#kV#_!NO@RG@B5lxBO7WfIAi@o`{_XQg(*{R=@Z(0ij+*i7sK zW5D%_fRN7l6qpytW2K1lUqP&W5jDT!AA9@q<;M!T=CKv*^MP)Er_uLL+Y53>**w7Y zQ!2?^4$wC;Soc!+#~d?Yec;NLdR z{~*hrSQS>UOMBe)1pHe0EsyO@d(IrU4ZiS&jL`wqv6Oqv=HbI^70qu9kn~wGkNL^> z!Pd2)i--+&zp^`#4@*Myg;3r(jt*h@RWgRt70byZr;0Na8n4!bmpuX1&gK=QK!@j< zH2fF7@2s0H0!9%VC-BIp(99@e@<%Ko?BB9uv*xPnZ5dQr z8r7~9cZXv(AZPY^<(X@}GARv&_}mfYA7`vdl=)g2GIyN(<}(b_S_N2--NKp$SgO<3 zRx|EabcjUSB44GaH3Kxmx3SW;E;Eia2Zs5SkbkQ8E%VQqr0J?tQjF~p;nbIXn+D;? zg;t3Jg7A@9U**@aaqs}9;%??Scm{zBIY2ceYAQd*W-hB-!+H&4#yrm*GtT*&#`FXx zGIVm}G<;Pj+h*KQ68S4rcIIGw-mkl039s@O4p9F%TC&&&xRL=N49v2PdBb$MxJoMo zQk8+Sv+F5m{xP1prZvn1=x-Q z&Yox|y&arZrLTm~<%o}VfPV#z+i&{)W5emXhx^g~8>eUe)|Vvwp8-x8d-MOj%@mSk zZ9i{-Hu8m-rfO##y(_Rv;Y@?6%h4Id#6%`7ah+IaQ13o7o>bG&ScMj&KO~QoCmNT6()+oo%B zugV3Da)t>unQq=tbD)FP{JmB~S5QCmb)lq9Fp(*|(UGeXr3kR?k35sKFs{{a*y+h0anA_K@iCi;BR6nFmKHC=@)rMmu=XWS1nVqD*=#${cFJ6<{e=U7!Rbg>Y0b~d#&viX+5m9aNAv=RAMt8=n6a&@t^|2LsKMR7xF z;Cmw>t0<=W2II;doX`p#bcjPV9z&3dhAObzcB9xXMslqr(y!P6+2kG>Eh!rx&ZKmW)Wk~_xh`?neJqVhJk~1eTvRF#ehRwpS>s1{vUx*qf&Jm z$)Wh|lmwYatW@U@*$<14>^|yYwmwFs)C5ke9hG42{gilSU#^ulO`M}`wJ_4*-3 zGb?hfQj_AGQBI?4ghGijqfu>uAYkLK#!^uGUXuctdn8Ae5I7}o+j{9MJiM|sf9Nc{ zuP&Ls@?rMe=IfJo!=iX?9&*4!Yjs5d?0Yx4cIFXrkSHRk17Fc@yM__fyFLLl6O9nT zQqaDXunH;!PpQ7+-&#wJVtJXl8LjIkh)5qmcqhErYrP31w5~#!tS{LYTWGKEtbpE%(hH>qV(!2KMfs#a z?ZzzbDB}(7+NWIiSBQ<_{3>;H;z}uZI;n2PKWJNxM=l;5-^zpu-}+1x|38lS-}6GX z6F=M~bUtHg98X@of>mgCH-&5g6UpXGAla<+g`b&MQANW6D^;zfSzq0mQ)*J%;&tPOYin?J*G7GqmQ=>jvWvOn6E?! z{$(CU7}zChEnl$(>xf`ZdeF2E9Bv=eH&T4HWAOQ!9gBs z{gl^|(78q-ioBS^rR2PEGZLe_4Rl**H(bB?84RHquCEKi8N#29u=Eoh(DV`ZX{+8< z3BIX<`sOFNBziFWS#-X%(e`0C_|Q8;Pw9izjNOF8h|kvmWCmDHM&pANC9MV<wEJ;W{-jXqm!zC+Y@Q1y_lLL zfV^(1{A;L%TWmyI)RPknVUB<4r+d42S(W=%bXd@YB(~d>ABq-E;t)ie6%ouy(Fg`p zuj<=I7^PDs5H+UsG}+GH}zoGt*{yKF&n23C7aW@ z4ydrRtFW-uuAUu@RWe&0c!N4!H;`!n@@t#u zxlGQB4rx(F7#&MKHPy}EI;d+l(G{1KG!ZBE)7)@P!AsUCCCb0IH!P5TW=GoNFcif`NB4en16Cp<7=fhz7^uQAjbJBH>@naf2ueMktmtZ|U|)ICDMN2r`mgMSl=qDwHL;}L-d~El>pf8UJRts_03eTj*hVy6H z5o!>?AcffORZq9!NJNa`-W4wMfe6I{3*rYUhIMA>y|T}KZ56HR5XEs{(|x#SDtP@N z5?12L0W7qfvWl8T-V+u=fkBH8!$}g)7hRs34m7~)^S&Ar zd`Kz7$S2Mz(|5H(Dwn$V7n8K2pqhHQ8!i{G4C~Y6_Ex&Y%EyXdw#Nj}VdG`XCN_1n zFg4;3DGjjUo$%=m@ui%z$JU66QK^qywvLKZpD6ZQ2Ve2VBps8rcvJ6^Cf^#H4?UQ5PW$4;b)55yIY9}@k@48RLtJa>7bofX{EUE7 z?0Cx0PeYbbLAelC-BfqHf_08;{lzC1kwr|a>5{O6*g<~wt6KYPfP5uW0w?VTO!M~Q z6H@n{cONp`{>hVjEIkOV6m^ZP^l;mGz=T&*5&`m84astyZ#XZ6CpH384tt%vSJ zsvYDC5u`D&U_u)1OJ&D2=F*ie-7!%N+V6*qoM6m-zj|}hDZ+@?`mJ10OX3K-`+R0m zNk$^+zBJK7%It=_&sIc}&DT>!LYU{|WPNrp-Nfly8u5&3@(l{!pcPxek3^{L`<9*! zE-0KukkD^^+<&3BNJM$e0=~B$=VQEp@V`L+PsUEL-_%+E_kyR-_mUjr|D1Z2J->y2 zZNHTrzP$=uEKQvy4DG&+4*o5^8Kd?eI>5S#b;NXlSrGVnj3~e^OLe4*Qe7%U#4WiX z)k7h@VHRERR_j{wp8ALHdD6bj&+Dl^?2(MuL9*oTRUI3SQ2jJ4x#!GR~b8F(H6|clt%g_O=v(@*;;5eW{e)CsR{UNDIE{C-1@qe z7NY&S7DeI4?z7tR9LJ$e6za%qLsF(>%M?m1nQQ4htpl?P)yj7_C#Ds5k5F z1h@YlI%a#k9x6}=hs(mkRr-fSrmikEk)Iv6D`S==)-dDVbNK;4F@J7iC(M!K6l<^lm@iXKpYbd7b{_0BDjc9ju~tFH7Qfcgu>A9~3tzmbFnXbS(pWES9955Vbu=iI zX>GH$kbD_?_fRojp{~Mz+%=%RHG!3l(wxQb{zQlW&MTlbr2*9|peUBo#YZ8u!UMPz zJo9lmW3isPrkErmxp&SA4Z4vpe~LLL-w6JUW}f*bf#w6lVyDvUhdK9fX!p#TT3fL+ z7im|;28gcWM)UdfRI;603BWd`d%7#sP0t)qNW*R*WmrD?hg37Zngmu{P;Lm`rlK_> zITGMQH~V(}6l6}TeG5nPEHYI3EHiY}TD%AAQ@%&*Q@w}lLp!VC>E;PCjzgVyNqNmA zYd0t~-pn55?#)1Tc-(xbL07m;Md14bPJOLyoRpLhRx-BtH{Z%<78P>0$olxWy4d9! zncKIDHrWFnBRUUqc`qiz@xrz52u-?2kq~5n$h}&*K?MxJ?xV?vVXvLErROVl7L9s; zedsv`#k1PCWY;`{${N?=R9%uy1P+jKf$&__RLHP zWVH#4;U{}bB4D^B*hm%nhRpQF{4?xW$&|oNp2CUE?Coyj1QI%P|w91%+*lty%ecgZ$I1|mJWq9_c?+4{KElHR%TIU zf+^4^hXY?f0&(|Q5=NG~AhiIVR+(a1gF)Q;L&vH%zPO{yydKt*(f#LehU3CVRIS&* zA1khb+xXe{29|Ggayz;nqv9M8n$JYj?Z!w0Sb}^lq#XQlg~=nkBhYxmlB{huZcL}F zA6sNZgJpJ|laA>P$V#ZhT+&$nvNM2sudEEeUaohc#ab+sC zrj7G)E-#;G-w=I1hTjN@b;lAjX40pR+<>)=n`V_!(JFk*yE zP3nDEs^C9DCSbs8`TV~U17Bmq%9I^$2xWK;N>;W~^^HOu)jQt*LH(-WD@UyR?lk$o z+mZhVgYn<1!ov1;W|rozPKN*0V#Xxdelr-6M$Gf?*Y~BQbHRK-&@B;ni(p_#pe0mg z(1pQKcH#lqe^P^eZVUta>(kWOPSnhH^E-oKtcJzCI^FSuJ zze(PI3_%VP4Fp7k#GyT8c6l?vndL`$$s5Z05+P==upnazJ>&{eIc?MW6fVO34pXfm zmmilQmRYtQ*e*BV>J{aqI%F$j*;=Tdx{msYgM{2Gd`D^TU>~NLKrbqtQDh6KPGcB& zYEY{fj~P1Q zY_vIx8j+W?nOTo{k7|A!vvlK?qYKZnTkm@qV7lWQf#;J@)(qh~m07vHwdQ@701t>}N2> zYt=Q^?p;5oP%enrkvLCarS2rlJ;zjT@1)Ha_28t7T(IMcZi3U?D_dTzMKnR%{b7 zXeWL6f-xfJvhsVNF_?I2^3gmv=2|f7azO~wc+o|=2cR+N_<9sF;vio2z;vtlV7U6o z%q9XNPhjS1Fv)QuRq|0#HVGw&HG!!t0wQo=W>hP)uYZ7o;_qdM=-*`k-Z%4+>VGZ; z{vGL`lv&#q*NFJmy`%{yAIPrAB%*freDk*5cHaNPB~B86YH zIw9gNDz9H+n0&}J-c0V{E(`My-2Nkt0NBY-PjL5r*s48D&j)h7pIpJUb+0ol1F*~` zp1!}vw0*&IA^z*SXZ}pIG9;ySrW01 zpU6d%LB2t@(;)LD!*G(DXK-!R!}Bp1mKS>Uu`^#p z>~WR%dn&;>iuz9Pv3W7EPX~GtnCg$63a-#A$1B7q;ZqH{xws^Pf-V1eO|D zHXE9qC~c)%CS>n>jc?m)ux2hN2UpKIU2hP(X}`Ljjc|CDFH%asVJH&6j5&Rb6aaVeQvSt z6VIX1X(pXAmxL>}wO&QIImzI9LcFhECJ|Mzi1FWhCgS$=^!!D3^vyEEY0HM0>?fsv zz1W(i8*H{v9APY$IW@J9NQ06Y@g$&STTrPC$I1{t0ptDZ=rHjEZnN2BSw{(Pn+6KD zRZ-hjn-KgzRa=ZoUs=W0cAc-}66Rmi)kZgub$G6zPQn>fM&}9X6!J^UsbVFdewj#M zt5erf{g$1$WV`h=0<2Y%iDK|HwH6hSu-8LDPknW`jl$UfmI_z9=GkC(@A$oVsRFl` zMYdksp797E2vzaH-N_%;t@q4}Z;FxZ(y&6&(#;_uzaGV+M%CB= zVNRMN3tj1#%##v%wdYNDfy0)|Q$>JYJ8-6o*K4hcC(;5F=_Mn-l)y@UX$ zt$YU7Q%o3cqwRC6;{vbL1No%d&)=)2$$;SD9a-=PfFh$6P1;*I*d z?C_52JLp$(UF}SCxJXTY+9?uE`@f35}k=i`#4Rk6e@*KDc^(tnQcw(jY^fcG z2hqo(q%7)o0YkX;lCq$o6hgCi3n%i#6vZ7x&_k#aW{QnPk2CWm8yVytzz-Xd_05x& zK3Vo>SFs-R)cf&`{&tL=xJVe`-HvE7&mAL^uj`W z%$d@~HtC6RV)R6}b6PqR$Pa7R8c3d_D4Hqq2NfG(>kTi!rOp%>Lc~n3!5mddW>>pR zt8tmTCxnr(Xk6g2^MqN08AmxcFLP;APA}^V80R_+K#agUx(RR48L2ZQej@XRm?OF3 z&jyIH+L2f<&wdR}X$XB~;2tBIf^AThY(zLA4*i6@9FdbT!Xy~7Ywt-zdi=wCIRuOL z73^T>|0wMU6&500dh%`EqjoMKS;Z+_5iFfnaLNy+B-@vyNWRdcmRaaBUdtQvT_Q17 zTG$aE4SA0iRA}+d@r;k~BwsTn@=r*;LgW8Q~>>Y9oke1Rm(xx!gv){TQFv|25IK_jjLj z_mxH%0-WoyI`)361H|?QVmz7;GfF~EKrTLxMMI`-GF&@Hdq@W!)mBLYniN*qL^iti)BMVHlCJ}6zkOoinJYolUHu!*(WoxKrxmw=1b&YHkFD)8! zM;5~XMl=~kcaLx%$51-XsJ|ZRi6_Vf{D(Kj(u!%R1@wR#`p!%eut#IkZ5eam1QVDF zeNm0!33OmxQ-rjGle>qhyZSvRfes@dC-*e=DD1-j%<$^~4@~AX+5w^Fr{RWL>EbUCcyC%19 z80kOZqZF0@@NNNxjXGN=X>Rfr=1-1OqLD8_LYcQ)$D0 zV4WKz{1eB#jUTU&+IVkxw9Vyx)#iM-{jY_uPY4CEH31MFZZ~+5I%9#6yIyZ(4^4b7 zd{2DvP>-bt9Zlo!MXFM`^@N?@*lM^n=7fmew%Uyz9numNyV{-J;~}``lz9~V9iX8` z1DJAS$ejyK(rPP!r43N(R`R%ay*Te2|MStOXlu&Na7^P-<-+VzRB!bKslVU1OQf;{WQ`}Nd5KDyDEr#7tB zKtpT2-pRh5N~}mdm+@1$<>dYcykdY94tDg4K3xZc?hfwps&VU*3x3>0ejY84MrKTz zQ{<&^lPi{*BCN1_IJ9e@#jCL4n*C;8Tt?+Z>1o$dPh;zywNm4zZ1UtJ&GccwZJcU+H_f@wLdeXfw(8tbE1{K>*X1 ze|9e`K}`)B-$3R$3=j~{{~fvi8H)b}WB$K`vRX}B{oC8@Q;vD8m+>zOv_w97-C}Uj zptN+8q@q-LOlVX|;3^J}OeiCg+1@1BuKe?*R`;8het}DM`|J7FjbK{KPdR!d6w7gD zO|GN!pO4!|Ja2BdXFKwKz}M{Eij2`urapNFP7&kZ!q)E5`811 z_Xf}teCb0lglZkv5g>#=E`*vPgFJd8W}fRPjC0QX=#7PkG2!}>Ei<<9g7{H%jpH%S zJNstSm;lCYoh_D}h>cSujzZYlE0NZj#!l_S$(^EB6S*%@gGHuW z<5$tex}v$HdO|{DmAY=PLn(L+V+MbIN)>nEdB)ISqMDSL{2W?aqO72SCCq${V`~Ze z#PFWr7?X~=08GVa5;MFqMPt$8e*-l$h* zw=_VR1PeIc$LXTeIf3X3_-JoIXLftZMg?JDcnctMTH0aJ`DvU{k}B1JrU(TEqa_F zPLhu~YI`*APCk%*IhBESX!*CLEKTI9vSD9IXLof$a4mLTe?Vowa0cRAGP!J;D)JC( z@n)MB^41Iari`eok4q+2rg;mKqmb)1b@CJ3gf$t{z;o0q4BPVPz_N!Zk0p~iR_&9f ztG4r5U0Fq~2siVlw3h6YEBh_KpiMbas0wAX_B{@z&V@{(7jze4fqf#OP(qSuE|aca zaMu)GD18I+Lq0`_7yC7Vbd44}0`E=pyfUq3poQ-ajw^kZ+BT=gnh{h>him533v+o7 zuI18YU5ZPG>90kTxI(#aFOh~_37&3NK|h?(K7M8_22UIYl$5*-E7X9K++N?J5X3@O z2ym8Yrt5Zekk;S{f3llyqQi)F-ZAq;PkePNF=?`k(ibbbYq)OsFBkC7^H7nb6&bhDx~F#muc#-a(ymv|)2@4)NQw!cgZ|NLJ@N6o#y!T* zi0kdtK#GC8e7m#SA9pSuiE5bOKs^ox%=l6KBL?8Rl;8R~V>7UCaz+Y_hEOZ^fT}$m{$;GJt9$l$m3ax6_ro{OH@r z8LmGIt2C9tM6fNUD<(Y1Q8w(aN2t@VPrjc;dLp9756VNLt9&>pX!L*6kyU=uui9e7 zrQ^&h7Nuk|fa1WH?@{DNg}C&i2BPX$%)+AMi%-ImT2Q_QnRV)3UbO2JW7T-JYoYnU!(}tii1LAN|D(%7cL@IEI0mCT0!t|kd)1KahVC2K z|9L76JA1F#-=|{!eJcN|r2bI={kK#3M*^rokSGIa zWe@gc$gT&!Q!WYqGHNy3PlhBvcjf&X0o_R>a?DGQ`e|uWa)>YuWk(ibM6r_Xpiaq4 zWtcFh6k&ih==f(%+T$`L1EYJ^CeevsviNKGK3iUF&1QI!EZOR4y2d?z{kh!@hfoR4 zR$n!oTq-{w^eSf-ckrX)rp`@DG4(8%e{AtoKlwoHjNIX8hY>P;3y*y_O8XZ8ien=J zQR{%EX3|XA79>Al$+8(rw$Y~9ydiaH!@*{;*H_Weng(B+tJe^@Hh~lm^J?rL_`0$g z%o51AI)M5AP4)R##rWU8U-|zQ>N#rK?x?C*TS+B3tQmUYjh6X32PBq4xJ`|D)tg%M zLwd8z7?Ds5CNhvE8H^bY$XD*~ke$yZo!3P40jio4f0GcqUohXX>C;+gOt>>PizdRd z?{b{G8+tZA!Aj6GmXFD*thAzMDL!h{90}jI=PdjS093DQi3v@l|5~^hKrwR6 zeUbcTjhPDLUg*ao;c>8JN}wB>MOIE^vN22t5147OVW>!BTDvz4xeP$B({i(Po~_BL z9*#5s@;l~%7S3?WkF0}E8>iN+UQZh{-D}3F##`x$+YG@H0vyyD%vY!zsJHcnGrN|& z;j<&E%0i6kwaMT{tjp$m5^V4*+9;13^DDjgaFvvOe3=j2hWU3(PY)kFXvfx#EJF(V zM!l@%;xJuF3pERftbWw~WnR$A&ok4UQ0dISRjNi-j7>!WdGm0^FUmns_uy2DYX1!< zihag3z-a%BI*WE?er9_UTY_Eui-R>cvS1;=N#Bv{mPKKIv5O9iXS- z3|WAAOhFjGB1il&5F9vj6Vm!t99VnZ6v)$mKW$!I)_=41msTtDQ`CAV`azZw#(aSt z5XK052F(2mTOy|hb~KaAM@(Gg9l3=rqXB79Zp!Q>)*)Hhm(8O3s53@BCx_ltYRV=o ztb3!SE4UlbZadeiDcr2NZnT1}MNd0Au}VRHKQ!`nW(2!sPW5ulYI zosR$tFs@ul-q2)^z}}Y;3$Jj4J#kik5ou3xxf)_JL$5C!E%MDFH5fza9unrHXXw5F zHY#AcZSU73&;sy;y;fM_*p0Txd{DmQVYSyT(8Bu@vSLZAPKlVDd&6%bHj%HaV1{=L z91uK99)#H)!*Q6S`Dv))pyUoDkMa0Sllw7Fvb!iKKjbR3>q-@zp>$lcNLt4(&F9yk z!g!~88ulk{z2xgG-3{{il~#8wah-S$PDsv)h$4v?e@iEW{%JRU21>lL%fw8~(DT#^ zywKIPee|O;<3lWQL$hEWAUeA2)~-xA7yV(I(Pe55DMTFD&6fP6bS3JXHE& ze2nS2pMh>pdB%}#XYcS*N|SMQmQ2J&7WZu72OP zj&wXEJHG2^_XZLJUco>yC|q(0L~1fPN+}|}7%$xcp-i$$kXV=D`~$(T`2Y)+8U2yu zvr%Mzd~RzcUfF#X_+uh&RV1fO9P&C;yFTuW5sb%e_xPYEB%AgtaOJ(ztnLEW_Hao2 zZHV-;f-^2epH zxn#@~NOA z11ZBV6tw5T5>Iz^Jb)0%OIlra;qJl^ufG156Ui{A2$qpZ_{^c1^R`+fbi*WT%;He@ zyieltZ{6ivdgz6i=@iEldc;jVS!5E5$rymBrD?v#K?Mr`?ocG-n&lL`@;sMYaM2m6 z)Tt641KSaR_(MIZi0J-0r(53x)8LPvfBwp-{yFxkKiTU)pdB)FGjC~7AfTS_$=v_Y z*Z#MJ`R|V^X!eb+h*>&0yC}OF{rl;vioX)<^+YRtY&IVpwZx%m(G%kbE0AM%G$dMnxO@9U~x`$qY-b?f@fkQ`9pNJeiFRud6ZB~-h_kWX>mCgONAn%y8FDS z1jJ5f3AGpr111cNW(=njoJxN_XIF;t1dO^e0km*ZO?76yVM(*B>Ix?cT=nC+o2XP$ zo!&hK$H9sd8H07(XoY2&7QG(*iL;qrs4U*82`MFg4P0Dzw%rEFXuGLBslk;D|Cf}sL{Bdj9TpChAGEEN*DvCLV(j_N-e zcLNc98=ZJ>3?UluoPSL2QwygpEHOrNp?KEVT77e1i3zzY%Y9lStpis{$m zm(cz{%HDxH)4xj^O$Qy@?AW%`NjkP|cWgVkW81cE+qP}nZ)X0p&N}nVoOeCvGhF+3 z?b@|#SADRMCTILsR4>rrHy4AU0PJ{|)~M^(@q-e3hLdj7_}OdzCb7?6jvhyQy!)3Gv3ELg)6!VjwA<}NC@GK%{NI0 zJT}T#aRk{>TXHs_T?t5eRw>v2ntXC6^p*jkWo`a)WZ0?8&JFWArnx^e@#->FsW0`H zaG;x(iE*;8ugY6Nhw%)c!hpKUyX3jhGA*i6J6@(fUBPL$z{4dz!^d6OL#hN?41I+g z!KjR5!+yZ+z+Y#U0p;s{fV{jmnQyy>%`Eu5GUWo&fsZL97=D~-b_O#00NQ+zO>XS` z6cn1v6jGixMb@=ItgwK*pbiAms3``uBok32wSnIF!(VPSH!Aca2(cTt_k_R zo!iTIMT0nvu%dfM`Tm^UEy_oqiKOy5hANU5*kqB?bbwBoz>e&)X{#5b+bFeY#FB}p zj#JFe|1ix8(itqE%U8Oe9{8p+lmPB#ITX?HhA~WU^`aMeLagZ?{J#$k1(<*Ga=!-# z(r?kozXS&T@4ut}e53yWT>JmB5K8z*I`ZXC(_u$bUyRSI0_sa;;}c3a_~)8{7*#4- z*hR0l-h`v$GUX!Y8S$OAGx`t7Oh5c~5aXowl-+DBh(YT4|& zz2Q~Iz2(b(#FdLc$(X>h-N-=%K&sS{-j3KfIshl~vZ(yd@zZNg`=RANO&IW5GfVZE zs6mU)V!n_RSxggdO;6lhUb4T6hUvzQ$bXz{bZkC4QCxql0E>+~jH^F@J~OC%bQSnw z!dVcM*I_fSE>Yp7Ty9TQ8VjoGh>2rpcziKFwP#ZBOnF7Eb+fb#57*n=S;keHfwc zH49H*3q*cDponQrD`v$M1l5b=n=zY6HiA!3d-3ZhDZ+LzKN9kDW#xrc^yy*`$5>{c zL~=_5`{q}NdlgOp5;!td)>hv&2umQuUJip0G-qJ0O^3tqXGdqmn}Z9DTz4j33Oh6* zRs?8e!2wbIsGfGP{9#WZD|RF{E86KJLEy$vz9KuntCBzNS(>A~j5a$SlK;1USU4_S zB~S;>^=U+8Kqh5?r+Nbfvr>prvVolf25hJ>p9%wx5ew2uyC4l%vXv}jkoT5T@NOml z^@+(g=Fks#f9@XKR3CWI`oEWac$gIO`*&M%ga!iQ{=d%2|J9ZRjEt@AzT>j~_r7Ge zrikzvS+U<-JIh%phK;}dvq;P%#NIq@*-Ro zG795&jLHtK3kt@gsFnVb^geyY&Q#0!O5NK<5l`92U6zg)2z^ixqqM;dD69k{pn5na zjzCXM7%i#qTM&x#D|7;Cs8qI%RB+HS5}ROsznNr@l{c2b$1$=!oSc;%3db4qHN!gG z%>$rEZM~8pIiTEB<|bT*mBLb{tT1uWu6OFJ)KF7(hj^P2rs5QyMx#q_*|BJuoXwJv zyh%!-X{q#YM`heA8Hj!57>5|U9qR_sVak1r z2ZH_d(s!DNqIuDZc5gkw(w^h@n7~LZ82aCz6|aG^n5bXeTCFdW z7m@2Ej5B%8MSD2HAr*BPh~b^9^;NJ~HXJJX7VeGl(#=!DS?r0mNIH^}d}=~&Ui+B^ z_wm)B4@6oIZ9FP|3#qxxW6-_;>b*pN_iexjXi=h}e`(krgGC?N9fbTnyYPYIO6K}B zFA_P-suUrOEb6b`R1i9SkQ*s2Jb7^Y-tOTodB9(}j@~WUg#QJE`jW#~0+;?p-Oyv- zf|?tPS8>)50*6Qh^}EqVu&_nQ+F^C-IvX6tCg-UDYg3UXsv^pjsXxyJD>pVkh$z=?hWh9Cyd8bJRGUUU{A@XK zEFVF%XrUA0yYJ(VcELR{+rh(`Av6SI^lRD?z)AQ$gLvakWpQF`_zp{aqZKUt@U1H2uD*qV*seS(QQ2Dy-oc-O8X zMKUd~h#|T^-6H}`fk?iJx;2kI2$Jj;QIf6%C{vhRVjqTvaHy7Wq*g(r%|c-3w(n|C zr9N;Rs9JfUDeCWJFL}uP;Y0FDf(Wy};!IZ2zFjeU(d+_6MEJlaX*p=3D!D0b>op*k zuYr23N1W0wly8w74c#W1LpXP|?)nWr(3eXs$E(c&PiERe!JWE^z0mm5cg@7F`_!@X za8nQpF$jOM+JDY~nb?BoW=-xIQ22c3TFS?M{R<~rPg$le_1#FXz85*d|IS}UP|x1z z+ey;M%HGW3JB?4_`{vKeW ztvEN4bJui=CcnsQr$FVybke#RDpaIHY{GaczId-A9x@ zD;Gi-lJ9Iau-2o;`eV1*3ztzN3!P`Jxrc)3ocRRAct^jD5E<^lS-Z2}IFL)oUQ<%h z4?B_#BP>07`M}`7ywGkk}UQpFIOvRZx*v_~StXIsHv% zk|F{D@%%dlD`92rZ1oTF`=>D~IOsVT{euA~R8PKHPL!_>)`|SN9}+Q?LbiX7V;y|` zxRlL>%Ik$H(5Pr(Mxx>JnH-I0{je|Ff^ zz-BM|Nl%;W&QA{{-tTu0O+e~5f#GiJBzZraC7MNqDOlr?|LhqN(b;MvwI7GKiU~0K z{eT373oTRU0c$+Rhw4@XlTr&~#ma@bzsx0Wj}{NwfD$q4FH;&|U+$&78LfwdW8CyW z;OP%PLaqA+xw`)8&GY!c(BaeeC9Brzjgx$h5BNTOB+6D5tkg^CsI*KLgPcM%ya0vp zbV@C>a?WQSn!)u=q#cuPB(|i9nbp{($Sdf>!kHiclcaabX4aUu7DhI!LxJ!}0zu6Q zTOuR4jCzAp4HQB~$lx0-I*OxW?+7`C+)yPz2LhTJcEWDtrjrKPGYcx7JOz5>Fq1BbCwdcc~)V(_dWb^W^Cg+d`E znHou4u_BxEZ#{w1)X2Kp1f&31bB$h<4(gDTg@SKrHdbYIH!LCpjoWx$m6H?^Rn_?n zQtIMb-Te>usVOR~oBNm|$%EuM-Al$LI7T(caHlUC_)EwIwb_}nTuQcJOCTkj73b`fRMv9KQcH|un^M#jXkC}A*2{;)>XL4t%9j;TE~jj=;kQxkt|4?2+jG$ zO>MA4Ihwb3fs%0QJ?(xri>|+HFKQwe~VKVDLRp+kcn%p&_N|cAcOg@pMI36hxJ}`pdX&g37 z;cjX3*$bO0ZP)WGjS+*#9BPg-k|%%ld(u(z6#Rs)CdDq3v`;~(3yzuCIThvMSR?)N8k)5*zG&`Z5~4mo5!kDs8X%#wWG=BAOu>f;BBx)i={ZF2%pg&8u9OHu$RwHWi(Zrnb_F!S4}H4Pemup{B?g&x zU#uE<^xzLw!p;7LfV$qJaB~})?F?0goeb3_q^thbL^rZUwm(m}&9u{(G_k#^JTnZ# z?ls#Ol&@v+(`?BLI#?e_JDXMXZ{(A&w5)*9@rU$xbIzoJK{+Kq$9~gGf?d^9H95ge z9~bmk_TQ;pQR=n`mb-!up;6q>rJg5h&~DXGOL10ZCpZElV9+NXAe{ z(U{+>WGl-7n9_cB;esbv`zQd5PGDmtwrS6_?5O|j?f&4!=Swn)P&{DTRm#Q z?lZCaTsQRukADw>9hvymR@=x9j+`A^;gGe7opW<)l3(+nJ@lsz+RXHLf8DN7;}xZk z?qsC(lwIfrLNr`%cX`j&a39Sp*W&E5ABI{ZAa5xsdUx~eii8JeRZF~w%iTbC#CrAF z-f(##d2g%O_TH()d(?*AHm2=rhVJdR;EgIyP9gikuT_JX+bTqZK_f(F?2|1`kjc^R zBzDQ!BZWG%cOfa7HvQaL{Ub@Sf-hnaA$2DxLI5WNxlEM_Y{{$4dSJMYh7u9pnQdxV z4jn2yc%eOWUGmF0IvlC|>3K7RbP86le>*$oQf1o9Hu$U5W?FiyW4x15Ke~2{<~fNTN9&{nZ5ltn)|0&e(%8lU!5}Jn=P4>{Wc_V#@<*& z#iR_5lKis*QVSbHPz*U4gh7_7OW&h{zBrzGiDu1}dlO-OKldzv6xfgM1;iJBv)(xV zL*nOH>}C4e_pM>gMOIgr7fA9zY$T{1XY4SU7$v!*x(F28!b*5-sBQdSve9%p&6M3A zoF)u_&hxDVt(HQi+d30wc#%MI?O*#P7A-(aDiQVoVBc|#+G2bKX3W9;9o8 zD4HbHZV4&TIV&gj0z6v7AXq7b^MENIMn!!BR-tnjn>8c7k|S+hdv8|W%?0CbQ$7B2 z*nZ5BW(Fd9tQJwZVVWzfGE-5!b%f6Gtb7t<-@dIT#=TMz3ERX_;%e*+5i3(E=Fe|ao}{&(4(W{aQ4Aoc)ELdd z5xg&)DFQ19QdauMEM#(&`Aef|XP5yeP7=4gf8P)3_V6z`))+>cj3Zt1W8V+5k z6@?Vs07*I%!{dvD{3k3PvAAMT~6`Iim@M4XaO_%YOCvyx_aZ#OE zEoQCTV=MOnIy3QCDFvy%ko~6YBp3`2U{rdbr*BHVsIz1!_!-at!VxNhO7NC`mw*3v z`Ttu;@xSWcS?XvTO7%Eu&JIN?8S!yGelAjipZZjjL?kL>E`1=KPegVn$cd#Q3 zmrT=BIxi`@g_jH)Xa+_?g2hpyNK%m(2OB8!%k?+{0(O|w)+-aJ*9?afapdUc!Kzrs z{bs76WLj({R!@J8BMHvCo3*s0;2pzhzGX)r8;v!#bHTvh^<3+|+&~E$E|kdCik&Q* zvXm9N43@#(!o=hFvr%fQ&OT-!rqBw$jx?HZJdVPlcdD=K;SDr6uCWgM^>3>bYYyzD zw(m$e)>4rAZ2TKb((Vb1@C$)B zlGwcqUCU-rWbV8uqUIsl`VCcnOj-itFqI_2Vd=!Iq?jNi9x#_YHyx#bWu>p$(+<#3 zm8~w;gB*jg_f08pzm}{qhFqd*D)ma%t4`7=-7rq(#5?lpDE3t^qTn!nJd{~h0E~E- zRQR>Q81&d@rddwej@!YvrbA+RoMKfi;I-d?R$U8^y^k3xwU)Hbm+Y+5OD;`JOia_@ z@eFpvBey;1Twd9l*KHO!*;QK5)5hjZ6$t;DMfiE(0a6m5?s6M|m_vXC)Q4Fs9sn_y zI!or%?trl8Gt;p&}Jf;`yVHP@rsXhgAkueW}cmxLXHXddup{SVk z>^B@F*hxOnbBoJ8BbZ4}yNfh{NlUbMcb;7pL3x^mNLtFPzQXori=YGCNI{)ZAZ2Ki zs3qvR(7N>3nl%-R(nxn9g25ba>ww@!Zk2n&Ba}d16bhv_#ER1_5xYp4v>EZSD=SiN zawHYv%hwEpP%wK16R};MR@m~tu!hMb+v9EDkD&DX5wQI`eh`K1)O`&W>qHzi z!b-DJ&}vPMc~072@*LfJeLTEC`v}F87}68vWOcpLQ|U|l0V(wYixZ*=QHzP%b48F5 zDzkei^(!En6E0%9u}ZGpvth=98Ab7vbAkWtt0*l8ho~bKg&k)N)D{X)Sw;9K%Rymb9ZkXRbICW~F^rHlD@gHfrM)$z@z z$hD#^b4Oa|U>c*}O;;{gCD0tASCj@XM=^K~@*b&A(W9HhBW7}y*>zs`L6&b(Numk+ z?}W2dTTY-k=m`2Mn)4HUL~E6!TYM-44baeHe*R4+@g^O;S2E_999y!?b&i{oCw2p8XKj8~?@*s%WZ!JnBS*(vHBdP{u*jZ;&mPhgW- z$TymUXpLsqmETA3RIEm7PvM~#n2jc{hcz=P?u0)H3}EOmNcTzyZTDabzVJS};Lw~R z^_n%#OhfmE{M47|-{~Pe!$80aEMfivs=~;(cxH+gPUI*ZYK)Fs^CUuPfB%5wwKIf`Er>NFR$wv_^&lqkC2)JPA$tSp%^o25 zAg&XPxP;|y!~aPnY+-Z{-RB5sI)^EdId1W3Ryen*fIbqnZ*#ViWDj((OR4xJM)(;? z@Cf4i$TZxF!ziNG;)MR>mr=gWYsSqO1fHC|%#CXi%S_NF)#i?IVU?g9jGmIR0)3Bq z;tln(pGsuhYpC|QPZ-M*8&b?$?(Qip*nJ?akUU7FF0*UvGnI!R3f3ehEjPhPEH4?iI+hc$O*6CpeI~ z4Sg%6ZtDeiGX3M@Xb0VgXkGxN8nJgs*k=MrN#I7+%!m&e>Y)R!$GXr{Ox1#dMkdI= zlKCh%&BnMT;qlKbqHxO{`^lO_0%GE1Wrg?yydI<3s6he$-Lq$K9S~S3G^v4nX^Z) zB1xZCP}vgY{yApKcg{ysSWd~`b){kFXX{Ue7MRxdIp*Pn%tWiA;G zK}!DfOQSN$&ZWcr5-u-l7x|fv7&wHK*XJt#+uRJnB2FM~@^XCA<8EU7^5gaHgUsjK zVOWSyGNZpfk~vg>rhqFct7@kb;0^O2Xsel9!;mh_$I zaKvjBu*O_)8H>OOS4ydd6g-9Aa_$Ws${Ws6Fz0|USEkulnyRswYM|urnEWUey-5v< zK|YioRQPd{ip*!92N>e3y5>A+Nv3n4toNold<;@)Cpa-}o{A3jKdb?O!_ZABIy-wA ztzaL_l_MAt9Aem+gcuy}HD3IYtK{aB*hzTjXq&0A@uXRXv^;8|0?@Am=!pbiG=C5N zM)McoW~TRnVW3NZq1KJj+xK2C;;K|}6aa~;Hr(bM#K7Rt=}86*!4%lv7!SYq>1?b! zoj=E)44db=!=F?h3B5g#AL`+B*zeH*a^T`<+KZ^BuwjR)kT#^@EDMz<=4WrL{?JQL z(Midu5k`G6nx|MAl2Y&qGSM%%J)+Yw(FWm|z4fu4I z{{3wjNT2C$ql;!i*H5F{3gKU*q?bZrK0;+SlBwYIPElp%gqUQ} zu~PZr#qYvYE(y1#z$@vrcmgY2xRG0o>lUpzY=8Rxlo4QAjRJzT;NnCL<(mUbSdA4= ztVE89jFFMl`L#!Zg%3PXupV$V{iK<4bVwi2|NAg#!f#s}|6Tho-?jh$0}cQ0{CR|dmG3a^sq@LvxXZ)+3$dF}+2P(mIEWS<*7dvo6~{*oVgRl! zQj7D|**X2unoU|<->1K~fm%Nsb}uww1XK5 zPTkQf9B`IX6+xXBtW=vbHP=GNFEGLjjx=4n!T8k>P0Dxgg)8?1odzkeL#&YQ#Ot0b z=PB19V^dl>CF9vFxxuNE`{qHrf083@(u~2?E+QAb|ND4Ak^;V`^p(&%y!)wtA0#DI~1sjPy=Gl=Jk_LKV+s!Y^j?t@%~H!tX2)H zm{hZ!i~RL`v`e690}D)}3FD}V(vmxXyhY%K5Guq{_Mv9?v2lT{bOWg4Zu^7y1ar8n zmAHd)JADf~14}K&Kd>r_R}_x(PBD?%GkD@IDUklYfy|?y1BVdi#9312{)remsr!-H zjW0tu#v*ygyWbLt^s5_5MkpYWOUgiCwk>cCafD`_APTvKBz%WJjzlS-G2A*dS)qkQzz504s~eJE&!(*U_>0mr$HykbwGNoNWwCEjL=c7M*D!Nb`PH zx2NPxryn>XZ%|N7#-LQKLHw1-kG_2=QJ2=JLW=C*nydd_?z&Q5N}%86-u%7SV*Gb- z@Bf(i5)`(qXJx-{k|yJdb?lP{@*FHb*?$CWe>MafB>S6?GqJ~&cUG(*a1pK4j zcf{!2#D*VPQ_jByclkm!s~C_7tTThdil^s=WdwIgp0IA$=lH>9hCTx z5Xr)>@*R|x(DjaQ$DHV74NS`Whn+KWt~fSy84>OBxriMf6kUU4Q-kS1l88`oJ;U37 zBQ0WgFx`l;cSai&{i2YGMjA#*3na}+e^znG8aHDsy4bZf z{#LURLOT3~vp8(Iz0R{4 z(_8XLA)?)amfcWVTsCQ-sSBOwSm)13fLBY`sl!Db%2|ifT=q zA}^pepW;deI;)PQ&|m^3N#3nC$*tDKC&*TfWst8|sxfW&I?b{?nN`JNk9Ca(mhRwR z;e*YDD(uF0O__g-j`;qano_bd|GzAsI+Vubzr}$(&aq;>^uHkxZUTeJ#UKKb;6ZDm zXJ;v)Dg@N3+lUox9T)|rNJr_O>1gvqMG~O-x)ZQ{39k$k* zrcOGGtVyrDyF9^lp_*9wqZg(DHLU6pbt5$?+x}t^@`ZWLSOY9S8qUS0f_DMG--u2U zVVx5|fL}q@Sl3A;632wqbUjvV!&-8wpc7-pG>olAC=&9uR9P+aLa{6Tryv9JHBdyU z`QqpdCu5x$noe5^wes^G-+w6U9@E!NDHQLKi5hO!OIh=Gi{cttNKdQZov`>`$0}qW zwz3-)$gk3`583rGJ_}20tDDcVxc&m|+f<1AbLy?n*OZa;*e5mRaNf1g%?~}~d-9qg z)YnEg7G_l=&u9@fFIBKaalRbC<3=@@*feY>lRsNADQ15TvdRTJZ<)eCYVPqzdL=Ef zN5(>Vd%-(d`|e!KyLWUEG);_E!J-fhAOl=zUcrgVX1&hj`Zz+wvF9Oz%X4gGuONcH z%h?(;os*+5gzz&rd5$4ULvA`P^W&(9fPMjG4QPG?KhaXi@O6O|U0j#gaaIq8)g2TV zw^p{f?V!a@N*#6eiN&o9wm34rAKw#f?N|a+zzc!gN;w?_aaFF$hD3`u9UipKy2=a?eobQF_M*REf$ zj;+{$jx7^GXy!mmwnHMf3B}G*11Dl+ur+U$HV>=|*rWme??d4H)D^+~34-e<&T4fK z9ektGZMEA`+wEVx>}pcQ8=?b3U&4M_&cEw^b7&G~t`IahA*>38X=Dd9PK+d+v5AchxFfgIsaho z3^g-d&4HLt@zfMHx9?onm0BKMiye@&M25!d0|j0nObOP+ni%+TRkv7Sys6+6#71_3 z=3c}|gh*XvU|-!JP`?&KXx|m7=3b=XOQhwATD=v29v@f&3!tGPuaC{Nnek)Hkat;U z8D}L&CC7!O1(_;b_eTUDwOd6z&YPOQpDHX}OEqX&rqBLxbi6Y+6raWRuS~FCMLRMt z&#=5pIeXB!uFvv)dfz7vM;+QgV~i`G1D= z-T1{F=Svc>DCY7thwMnMEmQWBpxlHg7sL~EN*8FEl-J$-QY%K%J<1cYy3$KV zG+EM%8p|KXJPMwGyQmer(9LR9MVP?GkZ=w}PhCJq%Z)LsM&!Gw6`W|6YLt|VXVknn zG+d8xv`&o*XpcrIyO?E>GlQ59W6fo)hgdm&!us+gk&~Z(xzd@ocd|b&VXN{1iqTsr*tppm%|xZev}kgETo?Ip)PrPEKQ`fJY27Z?+iQ zPb+`K9I8RYFXR$~Ml+_RwfhqjPI$G<^2eQukio^mMUAfca=8^`P$}-3av))0#reBX zJO?KRoQN}PfKy6EWE<${E5oA4psTIXI5R3P!`afUEO#@F#cW6?SdJ)pjcBxn{HXms zby#DnxcBA!a)&`0rbZD2SYTN$P0#hKE_J>aS6t>Fk>J=OkHFT(x{~rHi3m`WL<=kn zYqLhsunHC_IFkJ)nD=}RTK!-#DyN3zk?9q}WQ|y1rKvmlPWbjHi7UlXup~E2|PJyPAGVueL7){V%z~!0G zXAH|iVbtT<`S2``Tz}5WNHpQkL-$|7{gJQRQ z{~K-@lS>`6>%9heUPf-y_RL%GwF=+XQ~OK*X5E^AVS9Hz$Yi?j*y$}A5lRJRSrKl( z3QcA!z)W=;sR?}0Mz~&?X z!oKp_GaPNka5j@l=_W8i_Ofa*C=4c}Wn{Tg&f#Kv>KXE-R$KfXiUCcU6VXc% z=8i?pTr4YAqN+|9NHN6(T6PSGByZO+A&`CaMYXfh0S?fVLF)`1*NWI$0?QTU>kd1; zGzWn5_-2B({Gn)x14cpGBq|78lCZr3xPjhMM!`-370O&|EV~3vDVO@igfR9m|9LnF``CmprMnO!UW=7QAFV7bZS z&97u9G63r&&SVh|)l9V;7LLGCY8;X~D^VDNon%jj$@1u7VD2c4OvIF-u>sc%Ihq#3{;M1c1{1p*hfy2MCQDBv0zVR>fl{I|lfOf;-g+=$^M zq0Rs#+yN#^6GhBtw92LZA^WH9cMTdqHT|aKv9`5>skD<(_o8oU-&XLEN{BSkLfhlzuyX9QH{N}qaK6~?EU{Kz zFf*F$WS+nvgybofAOzsSJB2OZAEG_m7vlWn+^D;_jaN7gg(HGtYw~px zw}w`idAI|sf^=i2^*GKT7v~wW-*+2JZJYOB6^uJwuw86RE7aIFD9F(*S)1|L=(x*R zBloIwb9(ht1|YF%8f9femH5?zGAQAwWo zyqo4TV2R=B`U<5m8wAeMHEHpWnOW5wp)I$xr(kkl)R;Oi0isun=y}c-l7LZ7m;lm$ z$q4Iy6Sc&$7dUfcx*n3=`*`*UR zN1JtLOUYS-=7UaFQks;9^B@e^CN+Pz{Jd$gh_F`j>;ZkK-Md1}-@#73aDFjIwBy*d zTlwKK`nqGu3$(>F?Ap8A?q4y9mka`bxGNnAlZNNKWA&(V)8YwF5nmp7j%ul`_QG%4 zaeXBNd7~ytMg3#Xf>6W<>tYbEa%-$6=;P^Sh>aUHZ+e~0RG)Xi3%`rEs8MS8uYqwNdw4SWVkOjZaf` zG5VfUUiPoOG}N6 z<{qp@h!mly6=>7I?*}czyF3Y!CUIt=0}iD^XE&VrDA?Dp@(yuX{qsEJgb&Q}SNvXl zg?HrA?!MH-r4JN!Af3G9!#Qn(6l%OCA`)Ef2g8*M)Z!C4?WMK9NKh2jRTsnTgfut9 zpcZ7xAHd%`iq|80efZ31m3pN9wwBIl#Hqv=X)1r?($L>(#BR+)^)pSgbo+7#q<^S1nr$1&0=q$@M&POX?y?3L&3X z!%^Atu025LgEZ~|-)Cd0=o8K9A{$sT;SHj3M?l{!Er;st5w=T=K2^hJ<$(>&P!j2m zy3~(Qm?r5vh*EGKNLnP31{fhbiIU~c2GX_wqmM}ik7)NF$bEYKH^bK?MD+uJ24Qa=6~Fg-o!gSX*ZYoo{fzTLs$371<;7oLD|PiS3s zz;aIW1HVCV2r*#r`V-0hw_!s4!G4R|L@`u_;)KA?o(p8@$&bkWXV*taO%NC3k? zok=*KA5vswZe|5QOQd*4kD7Db^c|__5C;&|S5MvKdkPtu)vo}DGqDpc097%52V*z( zXp%Esq4?Rzj53SE6hKu;Xc!&LMZPPIj;O-Gnpq&!&u5db7Xi z64ox137#@4w5it68EPn<8RO48KG_2>?+Aa}Qo7fR%&wXJNf2J;Kwm6Opddsyx$gY# zU+b%y*{cBju|sw!wOcY_sMFWX9(C02d(;_YQh1*sH9?j$%`tKJyd(j0PtK#D+KLHI zL;b*n{CZ7IBb}MUGdG3l2vFGJn3TOYJD$Hz2OOy*%!5a{!!0mvok+e+N zaP?Ndm;SO(8-v%yvu#Rr;qFSgZrKJxV^uEnX@L(r4)dZeyh@yRqoi@3M|#Hz`hHN6 zA|8#&oFv8+1F8t(#j1%Ywdn%N2uREt;@bFAF}2zeI2KE&uZr$?-SIwKu<5ThXn_}f z`@RRcJ!3;pKi>mQe)VU5;c)zA@b#dd(J?}$sg0K5L^fIm8%TV4|>Q?qdfMwAh4AM8l8J|tiSF32B4q`!TYj_z!4Lowq99lipY?vlC zJssf0Vy+@In|fg`2sUl$wDGr$XY+4g*%PhDjM^G!Z{H44gwY-ymOqXka)G3ulfWdY ztNvx4oW*}=5^&NGhiS)Vzwb4;K`^*tjj8h$esujKb7&}?V_cU5kQElGgCL<358O^% zcT-EwP>hqb1%_8C_5R4e#7RH zp@tA$bVGG}q@TDR#-_^YT6}Zo5~p_5P%C_pRxwhgkor!;FtNFF#cncoEHm=#?xtY0 z1dHK{(;)5CQJ`0upxdRV?(5PH{JISW%d+@v8FmbTh9n5TXGnM`Cs}{(AbDxaIg&O2 zg<~{fKtj#r91u9PujPqhkFt7tid?IZ={dML<$3sh;A*Hw=VP++12;lVguAyio!na#kaYeX{|8h3_;g*K=UEf zU*{ZR($$Bw*(h;CSO4{alBraU^)52&nxLKUxg=1N5MCBUJ+3a^`9#f?7=4#`&oz?k zoz-#s4C)f8Uk@S*VF!Uc>X}9M`_*gkn0&GI2R*j zUlHUy5b;rLro3?bBLIt%dRd~2lT@kjcfY~OL5ZmTl)ExZyt!)^K#1p>U~rdclk``e z>=zHu6Qp^z%nX2U*RE14f{$U0*Cf)LfBz-c)t%iD%3wxsgHpRPvieqZgEC0IX_Vkd zxh27*KXpXxYD=^PP&EtX{NlX zC%v9)Wz6De((qH}Jqg-g`mwJ!IZ^L?eE2PE9@#9U0T>jD%e^K8-Phz7cZ-bP zU%h91CvGtNYmE{gk=tex+96fK^!I7P7YI3Ma}h)ty%NEN zn}d&kVV1DM4tPht`B!poikUOE396Uy+VE|E*eQuq zoT8M0M&bcREYOX7Q)F5+d!xec;2;H!WO+!r;v#uo402OEt*q%vj)mC@8wg}HO02G( zYG=<5*Vgl3R(5)N@{y+rvBY9CgUHeN`qQLm*3;$@Ez|2z2j3@V_m6j4Kc{5MTf}GG zMS_qp%5n(5$y|Ke#!!7w$4KKAJmhA@sJLcoS}Mv+l^X$2DS9H)ezLP0LfVpNMIPwL2U@Y%%7Q7jPXmGSPlRwa7*y~EkqObIDtyFm)q z-D~m~?At^+db`FvO2uEi2FuK@`RaSN*`T%G!}yA5f-hG1SYtty+Q}}`O^In~cgi>l z=zXVDDNVH?QHtgup3*d46+OEicA^)pIn2`}B}8}{g`msSbzzvq5zHCIjU>OrtmbrG zU26iOxr*A6%_LC(|3nH@ef$16q%glnTl}ob+(w=A9Uk48Pe(F^%ktv(oHC2Ve4|TE zc6J5le1ZqXdLP~+(UY@`Y?r~{B6_Alh8Q{OmhufQSf94*GFtAi(lV<=!6wqxL;jck zOnpR+=HK3Nh}Vv}%LXPzn;0b#^5Afk3y&G)X}NEkE`~TM%tU-P1@^=msCxOyP!IRO zBegW5wZ@10CM!9*_|kF~ZSxrk>r^zyCL|dy9$~*`OX?>1)fL1l(|lW|G!``CEq!N$ zMM)W~G2zDb6wA#)D5OmIMu_&UH_5B%DJ#NKl#R!?QVz>y5jLrK(-JpI6LIGVyD%W9 zg+7;cE40;Rcv9 zkCrUgZ-H}IaC=aY8~7*9+Ny?O=Ep;yso*#-SesEGSa3T&e&DQ`k!p#Zgb<6@KRjgn zG+Z?LoNstww}#+R`Y(?d>>GG^ncorkoKX@REYSTD zQTYHMwNiE~9MM(>u%!3KVR=O=by_thqeFR&Bm;D|lW@>^unOrb^k9yd-=S2LH0S7} z>ae^bwruKEB*7m=)u$5MIo(`)Y+RR5o>9(DDDV623UMVck1##|b`7H%yjK9unoDGkVIKrG*dvN;2S3P_9>ckR6c?7n{s5v!i;dE&<_aDaPA_ zi>Z&SHW^bWYJr-2sb7{WC|0k-a}7>k3)*YgZora(7dVnK7b6?Y7U|>t*u=-aLgC3` zvnz>+QQ_%r^ePEJA5X6^`Ey@^#{dDW(QZr*A_L9Y+QI4?xFXAQ-JDe?&YmeAVN{2b zK0DO+&S-fQWDg`ab0$mQodAEemrA3p{cHbqx{yVqz5Ns6)Rixse^k(i5spvs@22QF zAhsD~>)rC%n(#M+D1!s?DFCBTRfNF~`N7kC8by+1samiHH9dbid%Masz0;p`l^GuF z)taCc0FD9!#^qP3B`G>vZA2db%ma*@6WNWW{*kPq^|f^R%Ee|F-FM69H)u|#Qt{qt zoi{%@b&~<}!vBf99Ef=ih~RNSh2LT6zvdLf+KCi=hu6#d5v7kpppM&Z;F3;`{0FxW z@#nY=LnIjx1?~XD?48~y)>Y&odjWF%6G64~A_3<{rx6>R zqF2ozPyJzzmcF+3AQwJQ@C?KEo|5k3xP%;^ZN*zpQBm5ho(*e)*zn8NzzzG6V?5V0 z2<7tkys|TInay6or7^K(y0ZdwJz|6$blXL}SX7s2es~5{gYwS3d>6k|3V9vz-#G3! zh@|-B?^JP~seJrS$&XAfp`RknZ!pFw@e!a9WgKijDz3K#6@`ifTCWHTa}Tr}n!~;0 zh0~X4_sEKGZZ^}8+X9!T7NazNv{%@nJgpJ8M;Oa zaYo_2Qbk6_j7W15!`+XKC!`+_)IGZ>r6X=buKUkQ*5wXs5}A2D@eYvF0{q(=wm znxEYB{>rdO75{|gy2>`^UB!(y+9acVVRieAMG@Lhf)g>yr+Ccgf8oy1qUO@L$n8@A z;nKV>muW=<*rD@Su=A?nhxTpx>?1>jYOk(ytb|TNwq8q1{;WERaWZi0ov0xFjiIm} z)PkKhn`#2CSuR?p?4)9Vk#`#oL)#q8!B*j3s+x*6kQ~2Pog{K^{k(=xfv{IP9MecW zCB_bMVE;HQS12k5L;tHHjhJ8m%07IN<1N(vQCG+8IilmMo{g$Y5nrPhSx`OH03*55 z;^!ZP!KR|h3~K&8O?uAqKie(}FOYVMt}S-M;FF6%#pX@C<8P!jbk&G&a^_Oj+^2Ys z*1tnnx4eOpd*hgE$xD+(iTw1TaGNs=4*;Pf#P`fd%_%)Jk|eeooma)pR9ka)Ek(PX zq2N$R8sio=D*TQ0BaO+M*8wF-0cR8Bq6vZjr?NAFhjQ!V_)x?Yxmhd9T8#bPWJ^p2 zVbs{=P2C~;GV>Zlkw%u3?OM9&TE|2xMT@t3uSiNEt`MOO*Q>52Wh>pfXJR}YW6XQ{ zJfCN%^ZlJU=RD7Ip3^zMKT-4Q8#0faYOd#r>yK58)sH5XCS>Yj%p1^_p%gSNX4Iai z%;dio52O@`qrWD0>K#6CJvdGFcB%`pA47@W5qIzGe`HRY=O5CK4bZvl6IkJj{#%r? z|A5O4Uo8)Ng;t9f!sRAIsl1a8=TST_Vn(m0i`>XCa0r`>YP-LwxB%^wu8;8+GdQv( zG^usXB?ocI0_)y0MR`T!?Us5ehia8>M~+$sXlUCRovE--QR@;Ys?Ozq9P(Q7ZQ43> zpIo}_{z39UhS{5f8wKSDu+TKfi+#n{O-~4Uk zh*EmSxYYrfwOxCYV}}!zL%2uIc%Oe$XRV@rFeWeka?;Z(XI{}`X?HJGyIgFm@ZX;w zsc2~^A%MTLdqhpoV!jr)}36>dv>Px$jJImpFCzVcs)1b7l%&=qcE;^ zEoSbtk#6sYkpC=iQX(3 z5EUP%LDh0p49U2=$~DIZhi;dDRKwLN8`|PiC-Echa#PXZ|6)S}wWEA@3f!rX>G_!A zphhlmxu@3JVRr3xOWD}*UYv04{*WHt*vT;0@pVLmuu52Mb_Vg9Wg9EUuA2 zl8?Jv5GSU+*{PO$tBpirns`>?!VL-cX@gZO&q)OL%2_8U)8r*4jrGrH`p2zV!T-&| zaf{j)uCI!{A{R9~aJ?$SZ?kk?jfE7FM%1sOCd&S0B(^ckufHtAOetsuspYrqyZ)x8Z8=dG=GG1lcFtKmoxl{>m zAakHGc|f5ZKh>>}F8qu)Y29d2Op+uf?qK|dKPwE!pPkfGl#Sa#?TmJfv}jA5;1`#= zQqplM=!3^!2QZeCx7wu8uWl9!IN85^zrmqGDxsj;TVs=EU)ubiDaD<*@ss- zm%Y-l)9@TN+_0W7Ml5XnEz>_ep>fFIL{5V-n#cCKFhy#0p;!@D!D-=e{(8;*$#2G- z-~F3cHNv>%;D819xg3-F_yHg8bD1W}{1-kQ-da2kMRP?r=@>BD^b5H6=`Lf3y6VPn$`%)-GW}O^kSon7EBP;q9?=n_7O67v9pc>!pQb z)auPuaqG5v3l(E)_GSI_vFY2BtlPgw{(hIMip%d;>9vWnej@q%qMva4iRPI|N7n7w z(!_tL^K*((d428fyiU(eFYzyaICWGnFx_T^a$3(A4p<5kwVtGjOSNa=ey z3;wiIDZDmghb8BsMcSVyT9^W#{YkoGJ9As)0ccff5 zB`U1^TKO@jql!utGX7_6ceT=$mJTWcQ+7_Fk7=jIE7Lu2Ja%~~6K=X$o@5Q7)=`Ao z%Vptz#p~F$l82kO>0*a`LQ8HomkN}$Q0{w8GzfUMX3_$LbiUMT6?eJhshLtmT2m`2 zrK@zuUt8C6$2Zb?u5HM~2xm~H)s1rOJ^3v#{cdG~?xM<+6Lrd(chPMthvmtIcgJoV z-(H!YsUD=t^F)QFU+e|WYBXo`#ht!`&flPI?tga}(nLX13WI~;V?XO(57wx&_pbkw zBgcA$g+wx2w|Xvakrlw=n~x7nWeO7*SwR2(p1`8M*~Ae34SZ&}#$zt|Z%!C%XpOXbpLFv5`sjlu|+#!Pgo9FXG>J~QZn(O%YH zBWQs46dZC)E;!SviJp zefD-koJ?SaKCq_$3t)wALZM_9CQK zGw9iXX^iWLHTQFmME^y==>muB0FYBWAg>aJ#z};63aHSV~ z^&BI1Xx6m%m3k8-P|$7QUIaSpT%uDW?OD?BB+n%~l7+?9t%+Q~hX?=}`?8pcPE~ed z2_t~uEm#W0-QN{N#+ApD+=zZSaBm3ob`3@h+u^Gh4ttNN2s$sX!nzuwp?JOsGoHwj z2@l5>ME8YD3`fUA=$RfY>9hSG4D8@onJ^lTK8T>xz1g7`#v+8NaNr$;IubZHjA0js z2L>_#pi_KLjIjbU(W!eWi-1dyWY}RDad&1C;~9SzVCP+CjBSB%W;hBDGdrDHyErp5 z5X#cSZWs?oRzdJKA&bh!#B=h>1`ELv5fGsjM;8grEB_Ml5nw!Q?T_Fy!`b1Xw-Oi& zJK7`IPZ8{}^QU`YChTvFFb$*GF~83#Ejd(!t%MOOCWZs*(#FDY@nJtyM5ys3r$RH; zGwY5D3&8G^h`_zm90;)SqJ))TM><4FJcR=#j{NChP1sZn(R`H3fhIePF<1&VWkIAq zW^y3K#-asQg8eTLr4LygD9v;SEK4^GSPFI-K%^#fIhF$V7sl;-&O{IvfwyiWBC85G z7MZzT=Na3;D)1g*L}lf9j#XxMO|l*@z#B0U0n~;6Q((CogEzq;QX^ml3_auK-QH(! zYRlFYydetV8<%jvXTLoPZWwqE2_hCzy1W?cwt!a;Ak6maMa=Kjv3M;3Tu%5uArNL? z-SSL!&nS5679sOBE+%t6kqdtVcsdc$>26x21CM6sb)#h-?QyJ literal 0 HcmV?d00001 diff --git a/hap/gradle/wrapper/gradle-wrapper.properties b/hap/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..d2e5af2 --- /dev/null +++ b/hap/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Sat Feb 19 12:29:13 CST 2022 +distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip +distributionPath=wrapper/dists +zipStorePath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME diff --git a/hap/gradlew b/hap/gradlew new file mode 100644 index 0000000..2fe81a7 --- /dev/null +++ b/hap/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/hap/gradlew.bat b/hap/gradlew.bat new file mode 100644 index 0000000..62bd9b9 --- /dev/null +++ b/hap/gradlew.bat @@ -0,0 +1,103 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/hap/local.properties b/hap/local.properties index 5956d59..b5ca1da 100644 --- a/hap/local.properties +++ b/hap/local.properties @@ -1,13 +1,12 @@ ## This file is automatically generated by DevEco Studio. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # -# This file must *NOT* be checked into Version Control Systems, +# This file should *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. -#Sat Sep 18 23:37:45 CST 2021 -nodejs.dir=C\:\\Program Files\\Huawei\\DevEco Studio 2.2.0.200\\tools\\nodejs -npm.dir=C\:\\Program Files\\Huawei\\DevEco Studio 2.2.0.200\\tools\\nodejs -hwsdk.dir=C\:\\openharmony\\OpenHarmony-SDK-2.0-Canary\\OpenHarmony-SDK-2.0-Canary +sdk.dir=C\:\\Users\\Administrator\\AppData\\Local\\OpenHarmony\\Sdk +nodejs.dir=C\:\\Program Files\\Huawei\\DevEco Studio 3.0.0.601\\tools\\nodejs +npm.dir=C\:\\Program Files\\Huawei\\DevEco Studio 3.0.0.601\\tools\\nodejs diff --git a/hap/package.json b/hap/package.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/hap/package.json @@ -0,0 +1 @@ +{} diff --git a/hap/settings.gradle b/hap/settings.gradle index 848717e..4773db7 100644 --- a/hap/settings.gradle +++ b/hap/settings.gradle @@ -1,16 +1 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - include ':entry' -- Gitee From 3b1ff3f6c4eb54ecac9e08bbcbc4ff006440f751 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sat, 26 Feb 2022 17:20:46 +0800 Subject: [PATCH 13/30] 1 --- hap/local.properties | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hap/local.properties b/hap/local.properties index b5ca1da..852ef8d 100644 --- a/hap/local.properties +++ b/hap/local.properties @@ -1,12 +1,13 @@ ## This file is automatically generated by DevEco Studio. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # -# This file should *NOT* be checked into Version Control Systems, +# This file must *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # # Location of the SDK. This is only used by Gradle. # For customization when using a Version Control System, please read the # header note. +#Fri Feb 25 02:49:49 CST 2022 sdk.dir=C\:\\Users\\Administrator\\AppData\\Local\\OpenHarmony\\Sdk nodejs.dir=C\:\\Program Files\\Huawei\\DevEco Studio 3.0.0.601\\tools\\nodejs npm.dir=C\:\\Program Files\\Huawei\\DevEco Studio 3.0.0.601\\tools\\nodejs -- Gitee From 73a80e895125115bb9e0ea3dab7cbecf8aa14071 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Wed, 2 Mar 2022 01:20:29 +0800 Subject: [PATCH 14/30] update api 7 --- hap/entry/src/main/js/default/app.js | 23 - .../src/main/js/default/common/canvas.js | 90 - .../src/main/js/default/common/common.css | 37 - .../default/common/component/ob_dynamic.hml | 5 - .../js/default/common/component/ob_dynamic.js | 8 - .../src/main/js/default/common/normalize.css | 0 .../js/default/common/runtime/debugger.js | 14 - .../main/js/default/common/runtime/util.js | 17 - .../src/main/js/default/common/runtime/vm.js | 4412 ----------------- hap/entry/src/main/js/default/i18n/en-US.json | 13 - hap/entry/src/main/js/default/i18n/zh-CN.json | 13 - .../src/main/js/default/pages/index/index.css | 17 - .../src/main/js/default/pages/index/index.hml | 32 - .../src/main/js/default/pages/index/index.js | 131 - 14 files changed, 4812 deletions(-) delete mode 100644 hap/entry/src/main/js/default/app.js delete mode 100644 hap/entry/src/main/js/default/common/canvas.js delete mode 100644 hap/entry/src/main/js/default/common/common.css delete mode 100644 hap/entry/src/main/js/default/common/component/ob_dynamic.hml delete mode 100644 hap/entry/src/main/js/default/common/component/ob_dynamic.js delete mode 100644 hap/entry/src/main/js/default/common/normalize.css delete mode 100644 hap/entry/src/main/js/default/common/runtime/debugger.js delete mode 100644 hap/entry/src/main/js/default/common/runtime/util.js delete mode 100644 hap/entry/src/main/js/default/common/runtime/vm.js delete mode 100644 hap/entry/src/main/js/default/i18n/en-US.json delete mode 100644 hap/entry/src/main/js/default/i18n/zh-CN.json delete mode 100644 hap/entry/src/main/js/default/pages/index/index.css delete mode 100644 hap/entry/src/main/js/default/pages/index/index.hml delete mode 100644 hap/entry/src/main/js/default/pages/index/index.js diff --git a/hap/entry/src/main/js/default/app.js b/hap/entry/src/main/js/default/app.js deleted file mode 100644 index 8e47aff..0000000 --- a/hap/entry/src/main/js/default/app.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -export default { - onCreate() { - console.info('AceApplication onCreate'); - }, - onDestroy() { - console.info('AceApplication onDestroy'); - } -}; diff --git a/hap/entry/src/main/js/default/common/canvas.js b/hap/entry/src/main/js/default/common/canvas.js deleted file mode 100644 index 09c486d..0000000 --- a/hap/entry/src/main/js/default/common/canvas.js +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -export class OBCanvas2D { - /** - * @type {HTMLCanvasElement} - */ - canvas; - /** - * @type {CanvasRenderingContext2D} - */ - canvas2dctx; - /** - * - * @param {HTMLCanvasElement} canvas - */ - constructor(canvas) { - this.canvas = canvas; - this.canvas2dctx = canvas.getContext('2d'); - } - setFillStyleColor(color) { - let str_color; - if (color < 0) { - str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) - str_color = '#' + str_color; - } else { - str_color = '#' + color.toString(16).padStart(8, '0'); - } - this.canvas2dctx.fillStyle = str_color.substr(0, 7); - } - setStrokeStyleColor(color) { - let str_color; - if (color < 0) { - str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) - str_color = '#' + str_color; - } else { - str_color = '#' + color.toString(16).padStart(8, '0'); - } - this.canvas2dctx.strokeStyle = str_color.substr(0, 7); - } - /** - * 安装到脚本库 - * @param {OBScript} script - */ - install(script) { - script.InstallLib("canvas2d", "canvas2d", [ - script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - // canvas2dctx.fillStyle=color - script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), - script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), - script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), - script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), - script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), - ]); - } -} \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/common.css b/hap/entry/src/main/js/default/common/common.css deleted file mode 100644 index 0806a85..0000000 --- a/hap/entry/src/main/js/default/common/common.css +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2021 Huawei Device Co., Ltd. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -.container { - width: 100%; - height: 100%; - align-items: center; - justify-content: center; - flex-direction: column; -} - -.box { - width: 100%; - align-items: center; - flex-direction: column; - background-color: bisque; -} - -.btn { - width: 60%; - height: 100px; - font-size: 40px; - margin-top: 20px; - color: #ff00ff7f; -} \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/component/ob_dynamic.hml b/hap/entry/src/main/js/default/common/component/ob_dynamic.hml deleted file mode 100644 index 62cc5f7..0000000 --- a/hap/entry/src/main/js/default/common/component/ob_dynamic.hml +++ /dev/null @@ -1,5 +0,0 @@ - -
- {{title}} - -
\ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/component/ob_dynamic.js b/hap/entry/src/main/js/default/common/component/ob_dynamic.js deleted file mode 100644 index 19f1cef..0000000 --- a/hap/entry/src/main/js/default/common/component/ob_dynamic.js +++ /dev/null @@ -1,8 +0,0 @@ - -export default { - props: { - title: { - default: 'title', - }, - }, -} \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/normalize.css b/hap/entry/src/main/js/default/common/normalize.css deleted file mode 100644 index e69de29..0000000 diff --git a/hap/entry/src/main/js/default/common/runtime/debugger.js b/hap/entry/src/main/js/default/common/runtime/debugger.js deleted file mode 100644 index a56d303..0000000 --- a/hap/entry/src/main/js/default/common/runtime/debugger.js +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/util.js b/hap/entry/src/main/js/default/common/runtime/util.js deleted file mode 100644 index 9a7c777..0000000 --- a/hap/entry/src/main/js/default/common/runtime/util.js +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import util from '@ohos.util' -let _TextDecoder = util.TextDecoder; -export { _TextDecoder as TextDecoder }; \ No newline at end of file diff --git a/hap/entry/src/main/js/default/common/runtime/vm.js b/hap/entry/src/main/js/default/common/runtime/vm.js deleted file mode 100644 index 7270a66..0000000 --- a/hap/entry/src/main/js/default/common/runtime/vm.js +++ /dev/null @@ -1,4412 +0,0 @@ -/** - * @license - * Copyright 2021 Du Tian Wei - * SPDX-License-Identifier: Apache-2.0 - */ - import * as util from './util.js' - export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - static objFieldGetter(fieldName, fieldRegister) { - return (builder, args) => { - let obj = builder.NObjectRegister[args[1] & 0xfff]; - builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { - return obj(st, f, local)[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - if (typeof (v) != 'function') { - debugger - } - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); - }); - }; - return f; - } - } - export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @1type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {number} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } - } - export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int - } - export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; - } - export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } - } - export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; - } - export class OBCodeSegment { - name; - functions; - fsms; - } - export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - Statements; - } - export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - /** - * @type {string} - */ - ModuleName; - } - export class OBMessageHandler { - Name; - Func; - ArgTypeName; - } - export class OBEventHandler { - Name; - Func; - } - export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } - } - export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - throw Error("Unknown byte code command:" + cmd); - case 9: - throw Error("Unknown byte code command:" + cmd); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - case 59: - return new NEW(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } - } - export class PositionUpdatePair { - targetOffset; - callback; - } - export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - RootStatementContext = new OBStatementContext(); //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {OBStructValue} - */ - /** - * @type {Array} StructRegister[] - */ - StructRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {object} - */ - /** - * @type {Array} NObjectRegister[] - */ - NObjectRegister; - StatementLength; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - // this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - varInfo[i] = info; - } - this.StatementLength = reader.ReadUInt32(); - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - let stmt = this.RootStatementContext; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset === this.currentInstructPosition) { - p.callback(newPos); - } - }); - } - } - - export class OBBuildInFunctions { - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward === 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let typename = a2(state, func, locals); - let id = a1(state, func, locals); - let r = StructData.Get(typename, id); - if(!r){ - throw `Can't find ${typename} which id is ${id}`; - } - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } - } - export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(null); - registers.LongRegister = []; - registers.LongRegister.fill(0, 0, Def.IntegerCnt); - registers.DoubleRegister = []; - registers.DoubleRegister.fill(0, 0, Def.FloatCnt); - registers.StringRegister = []; - registers.StringRegister.fill('', 0, Def.StringCnt); - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } - } - export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @1param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - if (type.startsWith("S") && type.endsWith(";")) { - type = type.substr(1, type.length - 2); - } - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - let def = this.StructDef[type]; - let group = this.Groups[type]; - if(!group){ - throw `There is no preset data of the type ${type}`; - } - let reader = group.Data; - let itemStart = 0; - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid === id) { - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - } - throw Error("找不到 ID为" + id + "的" + type); - } - } - - export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBufferReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let _length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } - } - class Relocation { - /** - * @1type {Object.:{idx:Number,inited:bool}>} - */ - string = {}; - /** - * @1type {Object.} - */ - integer = {}; - /** - * @1type {Object.} - */ - float = {}; - /** - * @1type {Object.} - */ - bin = {}; - /** - * @1type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } - } - export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadUInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadUInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadUInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw Error("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - let length = SegmentReader.ReadUInt32(); - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName === s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - // let typeIdx = reader.ReadUInt32(); - // let count = reader.ReadInt32(); - let vari = reader.ReadUInt32(); - let count = vari & 0xFFFFFFF; - let typeIdx = vari >> 28; - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadUInt32(); - let d = {}; - let cnt = reader.ReadUInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadUInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadUInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadUInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } - } - - export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {Number} integer of start - */ - start; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.start = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(this.start + p, true); - // let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(this.start + p, true); - // let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(this.start + p, true); - // let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let str = this.stringCache[stringIdx]; - if (str) { - return str; - } - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(this.start + start, true); - if (length === 0) { - return ""; - } - start = this.start + start + 4; - // start = start + 4; - let ab = this.buf.slice(start, start + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - str = utf8decoder.decode(ui8); - if (str === null) { - throw Error('no string value of idx:' + stringIdx); - } - this.stringCache[stringIdx] = str; - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - // let buf; - // if (typeof (length) === "undefined") { - // buf = this.buf.slice(pos); - // } else { - // buf = this.buf.slice(pos, pos + length); - // } - // let reader = new OBArrayBufferReader(buf); - // reader.start = this.start + pos; - // return reader; - let reader = new OBArrayBufferReader(this.buf); - reader.start = this.start + pos; - return reader; - } - - seek(pos) { - if (typeof (pos) === "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } - } - - - export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - this.Actions.push(Instruction); - } - } - // 虚拟机 - - export class VMInterruptException { - } - export class ChangeStateException extends VMInterruptException { - } - export class ChangeDestroyException extends VMInterruptException { - } - export class OBVM { - /** - * @1type {function(any)} - */ - Output; - /** - * typeName->[VMFSM] - * @1type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @1type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - // let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f === fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {*} callback - */ - Schedule(millisecond, callback) { - setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } - } - export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - if (!this.CurrentState) { - return; - } - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.data.Name); - } - } - } - export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.LongRegister = []; - this.LongRegister.length = v.count; - this.LongRegister.fill(0); - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.DoubleRegister = []; - this.DoubleRegister.length = v.count; - this.DoubleRegister.fill(0); - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StringRegister = []; - this.StringRegister.length = v.count; - this.StringRegister.fill(""); - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StructRegister = []; - this.StructRegister.length = v.count; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.NObjectRegister = []; - this.NObjectRegister.length = v.count; - break; - default: - throw Error("Unknown type " + v.typeIdx); - } - }); - } - } - export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {OBTypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let h = this.data.EventHandlers[msg.name]; - if (h) { - this.currentMessage = msg; - new OBVMFunction(h.Func).Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let hl = this.data.MessageHandlers[m.name]; - if (hl) { - hl.forEach(h => { - if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { - new OBVMFunction(h.Func).Call(this); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } - } - export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {OBTypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc, builder, args) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - if (builder) { - /** - * @1type {List>();} - */ - let LongRegister_ = []; - let DoubleRegister_ = [];// new List>(); - let StringRegister_ = [];// new List>(); - let StructRegister_ = [];// new List>(); - let NObjectRegister_ = [];//new List>(); - - for (let i = 1; i < args.length; i++) { - let arg = args[i]; - let Register = arg & 0xFFF; - let RegisterType = (arg >> 12) & 0xF; - - switch (RegisterType) { - case 0: - LongRegister_.push(builder.LongRegister[Register]); - break; - case 1: - DoubleRegister_.push(builder.DoubleRegister[Register]); - break; - case 2: - StringRegister_.push(builder.StringRegister[Register]); - break; - case 3: - StructRegister_.push(builder.StructRegister[Register]); - break; - case 4: - NObjectRegister_.push(builder.NObjectRegister[Register]); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - if (LongRegister_.length > 0) { - this.LongRegister = LongRegister_; - } - if (DoubleRegister_.length > 0) { - this.DoubleRegister = DoubleRegister_; - } - if (StringRegister_.length > 0) { - this.StringRegister = StringRegister_; - } - if (StructRegister_.length > 0) { - this.StructRegister = StructRegister_; - } - if (NObjectRegister_.length > 0) { - this.NObjectRegister = NObjectRegister_; - } - } - } - /** - * - * @param {OBVMState} state - */ - Call(state, uBFunction, localVars) { - if (uBFunction) { - if (this.LongRegister != null) { - for (let i = 0; i < this.LongRegister.length; i++) { - this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); - } - } - if (this.DoubleRegister != null) { - for (let i = 0; i < this.DoubleRegister.length; i++) { - this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); - } - } - if (this.StringRegister != null) { - for (let i = 0; i < this.StringRegister.length; i++) { - this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); - } - } - if (this.StructRegister != null) { - for (let i = 0; i < this.StructRegister.length; i++) { - this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); - } - } - if (this.NObjectRegister != null) { - for (let i = 0; i < this.NObjectRegister.length; i++) { - this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); - } - } - } - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType === 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType === 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType === 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType === 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType === 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } - } - export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return arg.Def.Name; - case 4: - // return "NObject"; - if (arg.constructor === OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } - } - export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - // 字节码 - export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } - } - export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } - } - export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } - } - export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } - } - export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } - } - export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } - } - export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } - } - export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } - } - export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister === -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } - } - export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - targetOffsetBak; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - this.targetOffsetBak = this.targetOffset; - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } - } - export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } - } - export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } - } - export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } - } - - export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } - } - export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFFF; - switch (specal) { - case 0xFFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } - } - export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } else { - fsm.Target = st.fsm.Target; - } - return fsm; - }; - } - } - export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } - } - - export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } - } - export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - let v = LongReg(st, uf, locals); - return v - 1; - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - let v = DoubleReg(st, uf, locals); - return v - 1; - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } - } - export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } - } - export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - - export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } - } - export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - - /** - * 单元数操作 - */ - export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } - } - export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } - } - export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } - } - export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - } - export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } - } - export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } - } - export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } - } - export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } - } - export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } - } - export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } - } - /** - * value of may by key - */ - export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return c ? 1 : 0; - } else { - return 0; - } - }; - } - } - export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return c ? 1 : 0; - } - }; - } - } - export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return v === 0 ? 1 : 0; - }; - } - } - export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } - } - export class NEW extends OBInstruction { - StructDef; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Register = (code & 0xFF0000) >> 16; - - let structType = builder.loader.data.GetString(stridx); - let structDef = builder.loader.script.StructDef[structType]; - if (!structDef) { - throw Error('不存在数据结构 ' + structType); - } - this.StructDef = structDef; - } - - link(builder, instructions, idx) { - builder.StructRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - let s = new OBStructValue(this.StructDef); - return s; - } - } - - export class OBStructDataSerializer { - relocation = new Relocation(); - /** - * - * @param {OBStructValue[]} valueData - * @returns {int[]} - */ - serialize(valueDataArray) { - let group = this.groupData(valueDataArray); - } - /** - * - * @param {OBStructValue[]} valueDataArray - * @returns {Object. { - let list = group[d.Def.Name]; - if (!list) { - list = []; - group[d.Def.Name] = list; - } - this.collData(d); - list.push(d); - }); - return group; - } - /** - * - * @param {OBStructValue} d - */ - collData(d) { - d.string.forEach(str => { - this.relocation.addRelocationString(str); - }); - d.registers.object.forEach(ofd => { - switch (ofd.type.$__type) { - case "StructFieldTypeStruct": - break; - case "StructFieldTypeIntegerMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - case "StructFieldTypeStringMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - break; - case "StructFieldTypeList": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - default: - console.error(ofd); - throw Error("功能未实现 " + ofd.type.$__type); - } - }); - } - } \ No newline at end of file diff --git a/hap/entry/src/main/js/default/i18n/en-US.json b/hap/entry/src/main/js/default/i18n/en-US.json deleted file mode 100644 index ac2a096..0000000 --- a/hap/entry/src/main/js/default/i18n/en-US.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "strings": { - "hide_capabilities": "Hidden capabilities", - "percentage": "Proportion capability", - "fixed_scale": "Fixed scale", - - "displaystyle": "display", - "hidestyle": "hide", - - "refresh": "refresh", - "return": "reset" - } -} \ No newline at end of file diff --git a/hap/entry/src/main/js/default/i18n/zh-CN.json b/hap/entry/src/main/js/default/i18n/zh-CN.json deleted file mode 100644 index 10e687f..0000000 --- a/hap/entry/src/main/js/default/i18n/zh-CN.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "strings": { - "hide_capabilities": "隐藏能力", - "percentage": "占比能力", - "fixed_scale": "固定比例", - - "displaystyle": "显示", - "hidestyle": "隐藏", - - "refresh": "刷新", - "return": "重置" - } -} \ No newline at end of file diff --git a/hap/entry/src/main/js/default/pages/index/index.css b/hap/entry/src/main/js/default/pages/index/index.css deleted file mode 100644 index 280f036..0000000 --- a/hap/entry/src/main/js/default/pages/index/index.css +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -@import '../../common/normalize.css'; -@import "../../common/common.css"; - diff --git a/hap/entry/src/main/js/default/pages/index/index.hml b/hap/entry/src/main/js/default/pages/index/index.hml deleted file mode 100644 index f4ed250..0000000 --- a/hap/entry/src/main/js/default/pages/index/index.hml +++ /dev/null @@ -1,32 +0,0 @@ - - -
- - - -
- -
- -
\ No newline at end of file diff --git a/hap/entry/src/main/js/default/pages/index/index.js b/hap/entry/src/main/js/default/pages/index/index.js deleted file mode 100644 index e317d75..0000000 --- a/hap/entry/src/main/js/default/pages/index/index.js +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -import router from '@system.router'; -import fileio from '@ohos.fileio'; -import * as obvm from '../../common/runtime/vm.js'; -import * as obcanvaslib from '../../common/canvas.js' -import prompt from '@system.prompt'; - -let filepath = '/data/openblock.xe'; -export default { - data: { - info: "info:", - vm: null, - fsm: null, - uninited: true, - updateInterval: 0, - fileCheckInterval: 0, - filectime: -1, - ui: [{ - type: 'button' - }] - }, - log(s) { - this.info = s; - }, - ob_event(name) { - this.log(name); - try { - if (this.vm) { - this.log("1"); - this.vm.BroadcastMessage(new obvm.OBEventMessage(name, "", null, null)); - this.log("2"); - } - } catch (e) { - this.log(e + ""); - } - }, - ob_click(e) { - this.ob_event("click"); - }, - touchStart(e) { - this.ob_event("touchstart"); - }, - ob_touchmove(e) { - this.ob_event("touchmove"); - }, - ob_touchend(e) { - this.ob_event("touchend"); - }, - ob_longpress(e) { - this.ob_event("longpress"); - }, - ob_swipe(e) { - this.ob_event("swipe"); - }, - initStage() { - let stage = this.$refs.canvas1; - try { - stage.width = stage.width; - let fd = fileio.openSync(filepath, 0o2); - let st = fileio.fstatSync(fd); - let scriptArrayBuffer = new ArrayBuffer(st.size); - fileio.readSync(fd, scriptArrayBuffer); - - let obcanvas = new obcanvaslib.OBCanvas2D(stage); - // let ctx = stage.getContext('2d'); - // ctx.fillRect(15, 15, 50, 50); - - let nativeLibs = [obcanvas.install.bind(obcanvas)]; - let loader = obvm.OBScriptLoader; - let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); - this.vm = new obvm.OBVM(loadedScript); - // // vm.Output = alert.bind(window); - this.vm.Output = prompt.showToast; - let fsmname = 'Start.Main'; - let fsm = this.vm.CreateFSM(fsmname); - if (!fsm) { - throw Error("No FSM named " + fsmname); - } - this.fsm = fsm; - } catch (e) { - this.info = "\nERROR:" + e.toString(); - } finally { - } - }, - onActive() { - if (this.uninited) { - this.uninited = false; - this.initStage(); - } - this.updateInterval = setInterval(this.update, 30); - this.fileCheckInterval = setInterval(this.checkFile, 3000); - }, - checkFile() { - let fd = fileio.openSync(filepath, 0o2); - let stat = fileio.fstatSync(fd); - let ctime = stat.ctime; - if (this.filectime == -1) { - this.filectime = ctime; - } else if (this.filectime != ctime) { - this.filectime = ctime; - this.initStage(); - } - }, - onInactive() { - clearInterval(this.updateInterval); - clearInterval(this.fileCheckInterval); - }, - update() { - if (this.vm) { - this.vm.update(); - } - }, - onchange(type) { - router.push({ - uri: "pages/" + type + "/index" - }) - } -} -- Gitee From d206252ea9a64acc57cb71c212ebbe47c8531b60 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Wed, 2 Mar 2022 01:20:43 +0800 Subject: [PATCH 15/30] update api 7 --- hap/entry/build.gradle | 22 +- .../main/js/MainAbility/common/runtime/vm.js | 8736 ++++++++--------- .../main/js/MainAbility/pages/index/index.hml | 8 +- .../main/js/MainAbility/pages/index/index.js | 28 +- 4 files changed, 4367 insertions(+), 4427 deletions(-) diff --git a/hap/entry/build.gradle b/hap/entry/build.gradle index 3e1591e..316c1ea 100644 --- a/hap/entry/build.gradle +++ b/hap/entry/build.gradle @@ -1,17 +1,17 @@ apply plugin: 'com.huawei.ohos.hap' //For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 ohos { - signingConfigs { - debug { - storeFile file('C:\\openharmony\\key1\\openharmony.p12') - storePassword '000000187A7DAD405B3FC2C0DD5A22D71E099DAF1952185044808317227A7B8E1222ADCFBF53B994' - keyAlias = 'openharmony' - keyPassword '000000187828397D1F90A82A02013CB2E0EE8914EB988241276E31A9C535BB1F75BE8D9D66EC3723' - signAlg = 'SHA256withECDSA' - profile file('C:\\openharmony\\key1\\SgnedReleasedProfileTemplate.p7b') - certpath file('C:\\openharmony\\key1\\openharmony.cer') - } - } +// signingConfigs { +// debug { +// storeFile file('C:\\openharmony\\key1\\openharmony.p12') +// storePassword '000000187A7DAD405B3FC2C0DD5A22D71E099DAF1952185044808317227A7B8E1222ADCFBF53B994' +// keyAlias = 'openharmony' +// keyPassword '000000187828397D1F90A82A02013CB2E0EE8914EB988241276E31A9C535BB1F75BE8D9D66EC3723' +// signAlg = 'SHA256withECDSA' +// profile file('C:\\openharmony\\key1\\SgnedReleasedProfileTemplate.p7b') +// certpath file('C:\\openharmony\\key1\\openharmony.cer') +// } +// } compileSdkVersion 7 defaultConfig { compatibleSdkVersion 7 diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 7270a66..9b77986 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -3,4410 +3,4332 @@ * Copyright 2021 Du Tian Wei * SPDX-License-Identifier: Apache-2.0 */ - import * as util from './util.js' - export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - static objFieldGetter(fieldName, fieldRegister) { - return (builder, args) => { - let obj = builder.NObjectRegister[args[1] & 0xfff]; - builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { - return obj(st, f, local)[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - if (typeof (v) != 'function') { - debugger - } - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - func.apply(null, argVals); - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); - }); - }; - return f; - } - } - export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @1type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {number} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } - } - export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int - } - export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; - } - export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } - } - export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; - } - export class OBCodeSegment { - name; - functions; - fsms; - } - export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - Statements; - } - export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - /** - * @type {string} - */ - ModuleName; - } - export class OBMessageHandler { - Name; - Func; - ArgTypeName; - } - export class OBEventHandler { - Name; - Func; - } - export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } - } - export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - throw Error("Unknown byte code command:" + cmd); - case 9: - throw Error("Unknown byte code command:" + cmd); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - case 59: - return new NEW(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } - } - export class PositionUpdatePair { - targetOffset; - callback; - } - export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - RootStatementContext = new OBStatementContext(); //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {OBStructValue} - */ - /** - * @type {Array} StructRegister[] - */ - StructRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {object} - */ - /** - * @type {Array} NObjectRegister[] - */ - NObjectRegister; - StatementLength; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - // this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - varInfo[i] = info; - } - this.StatementLength = reader.ReadUInt32(); - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - let stmt = this.RootStatementContext; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset === this.currentInstructPosition) { - p.callback(newPos); - } - }); - } - } - - export class OBBuildInFunctions { - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward === 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let typename = a2(state, func, locals); - let id = a1(state, func, locals); - let r = StructData.Get(typename, id); - if(!r){ - throw `Can't find ${typename} which id is ${id}`; - } - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } - } - export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(null); - registers.LongRegister = []; - registers.LongRegister.fill(0, 0, Def.IntegerCnt); - registers.DoubleRegister = []; - registers.DoubleRegister.fill(0, 0, Def.FloatCnt); - registers.StringRegister = []; - registers.StringRegister.fill('', 0, Def.StringCnt); - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } - } - export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @1param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - if (type.startsWith("S") && type.endsWith(";")) { - type = type.substr(1, type.length - 2); - } - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - let def = this.StructDef[type]; - let group = this.Groups[type]; - if(!group){ - throw `There is no preset data of the type ${type}`; - } - let reader = group.Data; - let itemStart = 0; - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid === id) { - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - } - throw Error("找不到 ID为" + id + "的" + type); - } - } - - export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBufferReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let _length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } - } - class Relocation { - /** - * @1type {Object.:{idx:Number,inited:bool}>} - */ - string = {}; - /** - * @1type {Object.} - */ - integer = {}; - /** - * @1type {Object.} - */ - float = {}; - /** - * @1type {Object.} - */ - bin = {}; - /** - * @1type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } - } - export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadUInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadUInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadUInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw Error("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - let length = SegmentReader.ReadUInt32(); - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName === s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - // let typeIdx = reader.ReadUInt32(); - // let count = reader.ReadInt32(); - let vari = reader.ReadUInt32(); - let count = vari & 0xFFFFFFF; - let typeIdx = vari >> 28; - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadUInt32(); - let d = {}; - let cnt = reader.ReadUInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadUInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadUInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadUInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } - } - - export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {Number} integer of start - */ - start; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.start = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(this.start + p, true); - // let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(this.start + p, true); - // let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(this.start + p, true); - // let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let str = this.stringCache[stringIdx]; - if (str) { - return str; - } - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(this.start + start, true); - if (length === 0) { - return ""; - } - start = this.start + start + 4; - // start = start + 4; - let ab = this.buf.slice(start, start + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - str = utf8decoder.decode(ui8); - if (str === null) { - throw Error('no string value of idx:' + stringIdx); - } - this.stringCache[stringIdx] = str; - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - // let buf; - // if (typeof (length) === "undefined") { - // buf = this.buf.slice(pos); - // } else { - // buf = this.buf.slice(pos, pos + length); - // } - // let reader = new OBArrayBufferReader(buf); - // reader.start = this.start + pos; - // return reader; - let reader = new OBArrayBufferReader(this.buf); - reader.start = this.start + pos; - return reader; - } - - seek(pos) { - if (typeof (pos) === "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } - } - - - export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - this.Actions.push(Instruction); - } - } - // 虚拟机 - - export class VMInterruptException { - } - export class ChangeStateException extends VMInterruptException { - } - export class ChangeDestroyException extends VMInterruptException { - } - export class OBVM { - /** - * @1type {function(any)} - */ - Output; - /** - * typeName->[VMFSM] - * @1type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @1type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - // let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f === fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {*} callback - */ - Schedule(millisecond, callback) { - setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } - } - export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - if (!this.CurrentState) { - return; - } - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.data.Name); - } - } - } - export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.LongRegister = []; - this.LongRegister.length = v.count; - this.LongRegister.fill(0); - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.DoubleRegister = []; - this.DoubleRegister.length = v.count; - this.DoubleRegister.fill(0); - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StringRegister = []; - this.StringRegister.length = v.count; - this.StringRegister.fill(""); - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StructRegister = []; - this.StructRegister.length = v.count; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.NObjectRegister = []; - this.NObjectRegister.length = v.count; - break; - default: - throw Error("Unknown type " + v.typeIdx); - } - }); - } - } - export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {OBTypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let h = this.data.EventHandlers[msg.name]; - if (h) { - this.currentMessage = msg; - new OBVMFunction(h.Func).Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let hl = this.data.MessageHandlers[m.name]; - if (hl) { - hl.forEach(h => { - if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { - new OBVMFunction(h.Func).Call(this); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } - } - export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {OBTypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc, builder, args) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - if (builder) { - /** - * @1type {List>();} - */ - let LongRegister_ = []; - let DoubleRegister_ = [];// new List>(); - let StringRegister_ = [];// new List>(); - let StructRegister_ = [];// new List>(); - let NObjectRegister_ = [];//new List>(); - - for (let i = 1; i < args.length; i++) { - let arg = args[i]; - let Register = arg & 0xFFF; - let RegisterType = (arg >> 12) & 0xF; - - switch (RegisterType) { - case 0: - LongRegister_.push(builder.LongRegister[Register]); - break; - case 1: - DoubleRegister_.push(builder.DoubleRegister[Register]); - break; - case 2: - StringRegister_.push(builder.StringRegister[Register]); - break; - case 3: - StructRegister_.push(builder.StructRegister[Register]); - break; - case 4: - NObjectRegister_.push(builder.NObjectRegister[Register]); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - if (LongRegister_.length > 0) { - this.LongRegister = LongRegister_; - } - if (DoubleRegister_.length > 0) { - this.DoubleRegister = DoubleRegister_; - } - if (StringRegister_.length > 0) { - this.StringRegister = StringRegister_; - } - if (StructRegister_.length > 0) { - this.StructRegister = StructRegister_; - } - if (NObjectRegister_.length > 0) { - this.NObjectRegister = NObjectRegister_; - } - } - } - /** - * - * @param {OBVMState} state - */ - Call(state, uBFunction, localVars) { - if (uBFunction) { - if (this.LongRegister != null) { - for (let i = 0; i < this.LongRegister.length; i++) { - this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); - } - } - if (this.DoubleRegister != null) { - for (let i = 0; i < this.DoubleRegister.length; i++) { - this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); - } - } - if (this.StringRegister != null) { - for (let i = 0; i < this.StringRegister.length; i++) { - this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); - } - } - if (this.StructRegister != null) { - for (let i = 0; i < this.StructRegister.length; i++) { - this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); - } - } - if (this.NObjectRegister != null) { - for (let i = 0; i < this.NObjectRegister.length; i++) { - this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); - } - } - } - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType === 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType === 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType === 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType === 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType === 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } - } - export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return arg.Def.Name; - case 4: - // return "NObject"; - if (arg.constructor === OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } - } - export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } - } - // 字节码 - export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } - } - export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } - } - export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } - } - export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } - } - export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } - } - export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } - } - export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } - } - export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } - } - export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - } - export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } - } - export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister === -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } - } - export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - targetOffsetBak; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - this.targetOffsetBak = this.targetOffset; - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } - } - export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } - } - export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } - } - export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } - } - - export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } - } - export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFFF; - switch (specal) { - case 0xFFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } - } - export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } - } - export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } - } - export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } else { - fsm.Target = st.fsm.Target; - } - return fsm; - }; - } - } - export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } - } - - export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } - } - export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - let v = LongReg(st, uf, locals); - return v - 1; - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - let v = DoubleReg(st, uf, locals); - return v - 1; - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } - } - export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } - } - export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } - } - export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - - export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } - } - export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } - } - export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - - /** - * 单元数操作 - */ - export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } - } - export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } - } - export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } - } - export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - } - export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } - } - export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } - } - export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } - } - export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } - } - export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } - } - export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } - } - export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } - } - /** - * value of may by key - */ - export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } - } - export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return c ? 1 : 0; - } else { - return 0; - } - }; - } - } - export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return c ? 1 : 0; - } - }; - } - } - export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return v === 0 ? 1 : 0; - }; - } - } - export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } - } - export class NEW extends OBInstruction { - StructDef; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Register = (code & 0xFF0000) >> 16; - - let structType = builder.loader.data.GetString(stridx); - let structDef = builder.loader.script.StructDef[structType]; - if (!structDef) { - throw Error('不存在数据结构 ' + structType); - } - this.StructDef = structDef; - } - - link(builder, instructions, idx) { - builder.StructRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - let s = new OBStructValue(this.StructDef); - return s; - } - } - - export class OBStructDataSerializer { - relocation = new Relocation(); - /** - * - * @param {OBStructValue[]} valueData - * @returns {int[]} - */ - serialize(valueDataArray) { - let group = this.groupData(valueDataArray); - } - /** - * - * @param {OBStructValue[]} valueDataArray - * @returns {Object. { - let list = group[d.Def.Name]; - if (!list) { - list = []; - group[d.Def.Name] = list; - } - this.collData(d); - list.push(d); - }); - return group; - } - /** - * - * @param {OBStructValue} d - */ - collData(d) { - d.string.forEach(str => { - this.relocation.addRelocationString(str); - }); - d.registers.object.forEach(ofd => { - switch (ofd.type.$__type) { - case "StructFieldTypeStruct": - break; - case "StructFieldTypeIntegerMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - case "StructFieldTypeStringMap": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - break; - case "StructFieldTypeList": - switch (ofd.type.elementType.name) { - case 'string': - case 'String': - Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { - this.addRelocationString(str); - }); - } - break; - default: - console.error(ofd); - throw Error("功能未实现 " + ofd.type.$__type); - } - }); - } - } \ No newline at end of file +import * as util from './util.js' +export class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + static objFieldGetter(fieldName, fieldRegister) { + return (builder, args) => { + let obj = builder.NObjectRegister[args[1] & 0xfff]; + builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { + return obj(st, f, local)[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + if (typeof (v) != 'function') { + debugger + } + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + func.apply(null, argVals); + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + return func.apply(null, argVals); + }); + }; + return f; + } +} +export class OBScript { + NativeLibHash = {}; // libname->hash + InstalledLibs = {}; + NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + StructDef = {}; // typename-> def + loadedFunctions; //= {};//function sign->function + FullNameFSMData = {}; //FullName->OBFSM + + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } +} +export class OBStructDef { + Name; //string + StructCnt; // int + StringCnt; // int + IntegerCnt; // int + FloatCnt; // int + NobjectCnt; // int + StructFields; // int +} +export class OBStructValueData { + /** + * @type {OBArrayBufferReader} + */ + Data; //arraybuffer + FullName; + Offset; + Length; + StructCount; +} +export class OBVariableInfo { + typeIdx; + count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } +} +export class OBState { + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + Name; + MessageHandlers; + EventHandlers; +} +export class OBCodeSegment { + name; + functions; + fsms; +} +export class OBFunction { + /** + * @type {OBVariableInfo[]} + */ + Variables; + instructions; + /** + * @type {String} + */ + Signure; + Statements; +} +export class OBFSM { + /** + * @type {string} + */ + Name; + /** + * @type {Object.} + */ + States; //string->state + /** + * @type {OBState} + */ + Entry; //state + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + FullName; + /** + * @type {string} + */ + ModuleName; +} +export class OBMessageHandler { + Name; + Func; + ArgTypeName; +} +export class OBEventHandler { + Name; + Func; +} +export class OBInstruction { + Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } +} +export class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + throw Error("Unknown byte code command:" + cmd); + case 9: + throw Error("Unknown byte code command:" + cmd); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } +} +export class PositionUpdatePair { + targetOffset; + callback; +} +export class OBFunctionBuilder { + loader; //OBScriptLoader + StatementLength; //integer + BuildingFunc; //OBFunction + PositionUpdatePairList; + currentInstructPosition; //integer + RootStatementContext = new OBStatementContext(); //[StatementContext] + + /** + * @callback LongRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type LongRegister[] + */ + LongRegister; + /** + * @callback DoubleRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type DoubleRegister[] + */ + DoubleRegister; + /** + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {string} + */ + /** + * @type StringRegister[] + */ + StringRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {OBStructValue} + */ + /** + * @type {Array} StructRegister[] + */ + StructRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {object} + */ + /** + * @type {Array} NObjectRegister[] + */ + NObjectRegister; + + constructor(loader) { + this.loader = loader; + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + // this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + this.StatementLength = reader.ReadUInt32(); + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.RootStatementContext; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } +} + +export class OBBuildInFunctions { + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let typename = a2(state, func, locals); + let id = a1(state, func, locals); + let r = StructData.Get(typename, id); + if(!r){ + throw `Can't find ${typename} which id is ${id}`; + } + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } +} +export class OBStructValue { + /** + * @type {OBStructDef} + */ + Def; + /** + * @type {OBTypedVariableGroup} + */ + registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } +} +export class StructData { + /** + * @type {Object.} + */ + StructDef; + /** + * @type {Object.} + */ + Groups; + /** + * @type {OBArrayBufferReader} + */ + DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + if(!group){ + throw `There is no preset data of the type ${type}`; + } + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } +} + +export class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let _length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } +} +class Relocation { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + string = {}; + /** + * @1type {Object.} + */ + integer = {}; + /** + * @1type {Object.} + */ + float = {}; + /** + * @1type {Object.} + */ + bin = {}; + /** + * @1type {Object.} + */ + structFieldIndex = {}; + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } +} +export class OBScriptLoader { + /** + * @type {OBArrayBufferReader} + */ + reader; //OBArrayBufferReader + /** + * @type {OBArrayBufferReader} + */ + data; //OBArrayBufferReader + loadingFunctions = {}; //[OBFunctionBuilder] + Linkings = []; //Linkable + + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadUInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadUInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadUInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + let length = SegmentReader.ReadUInt32(); + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + // let typeIdx = reader.ReadUInt32(); + // let count = reader.ReadInt32(); + let vari = reader.ReadUInt32(); + let count = vari & 0xFFFFFFF; + let typeIdx = vari >> 28; + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadUInt32(); + let d = {}; + let cnt = reader.ReadUInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadUInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadUInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadUInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } +} + +export class OBArrayBufferReader { + /** + * @type {Number} integer of position + */ + pos; // int + /** + * @type {Number} integer of start + */ + start; // int + /** + * @type {ArrayBuffer} + */ + buf; // ArrayBuffer + /** + * @type DataView + */ + view; // DataView + /** + * @type {Object.} + */ + stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.start = 0; + this.view = new DataView(buf); + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(this.start + p, true); + // let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(this.start + p, true); + // let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(this.start + p, true); + // let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let str = this.stringCache[stringIdx]; + if (str) { + return str; + } + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(this.start + start, true); + if (length === 0) { + return ""; + } + start = this.start + start + 4; + // start = start + 4; + let ab = this.buf.slice(start, start + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + this.stringCache[stringIdx] = str; + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + // let buf; + // if (typeof (length) === "undefined") { + // buf = this.buf.slice(pos); + // } else { + // buf = this.buf.slice(pos, pos + length); + // } + // let reader = new OBArrayBufferReader(buf); + // reader.start = this.start + pos; + // return reader; + let reader = new OBArrayBufferReader(this.buf); + reader.start = this.start + pos; + return reader; + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } +} + + +export class OBStatementContext { + InstPos; + Actions = []; + + PushAction(Instruction) { + this.Actions.push(Instruction); + } +} +// 虚拟机 + +export class VMInterruptException { +} +export class ChangeStateException extends VMInterruptException { +} +export class ChangeDestroyException extends VMInterruptException { +} +export class OBVM { + /** + * @1type {function(any)} + */ + Output; + /** + * typeName->[VMFSM] + * @1type {Object.} + */ + Running = {}; + /** + * @type OBScript + */ + script; + /** + * @1type {OBVMFSM} + */ + Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script) { + if (!script) { + throw Error("Script is null"); + } + this.script = script; + } + + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + // let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + this.Output('BroadcastMessage'); + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } +} +export class OBVMFSM { + static ID_GEN = 0; + /** + * @type {any} + */ + Target; + /** + * @type {OBFSM} + */ + data; + id; + /** + * @type {OBVMState} + */ + CurrentState; + /** + * @type {OBVMState[]} + */ + StateStack = []; + /** + * @type {OBVM} + */ + VM; + Inbox = []; + PrioritizedInbox = []; + VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.data = data; + this.id = ++OBVMFSM.ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + if (!this.CurrentState) { + return; + } + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } +} +export class OBTypedVariableGroup { + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } +} +export class OBVMState { + /** + * @type {OBState} + */ + data; + /** + * @type {OBVMFSM} + */ + fsm; + /** + * @type {OBTypedVariableGroup} + */ + VariableGroup; + /** + * @type {OBMessage} + */ + currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } +} +export class OBVMFunction { + /** + * @type {OBFunction} + */ + data; + /** + * @type {OBTypedVariableGroup} + */ + LocalVar; + returnType = -1; + returnValue; + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } +} +export class OBMessage { + name; + arg; + argType; + sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } +} +export class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } +} +export class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } +} +// 字节码 +export class LDSTR extends OBInstruction { + Value; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } +} +export class PRT extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } +} +export class ReceivedMessage extends OBInstruction { + typeId; + Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } +} +export class STVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } +} +export class STVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } +} +export class StructFieldDesc extends OBInstruction { + fieldTypeId; + fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } +} +export class GetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + return stt.registers.LongRegister[fieldIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } +} +export class SetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } +} +export class CHSTT extends OBInstruction { + StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } +} +export class MethodCallRegisterInfoAnchor extends OBInstruction { + RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } +} +export class NativeMethodCall extends OBInstruction { + LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } +} +export class FSMVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } +} +export class SLF extends OBInstruction { + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } +} +export class MethodCall extends OBInstruction { + MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } +} +export class BRIFN extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + targetOffsetBak; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffsetBak = this.targetOffset; + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } +} +export class BR extends OBInstruction { + Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } +} +export class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } +} +export class ARITHF extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } +} + +export class ARITHI extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } +} +export class LDI extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } +} +export class LDF extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFFF; + switch (specal) { + case 0xFFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } +} +export class RET extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } +} +export class FSMVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } +} +export class CreateFSM extends OBInstruction { + FSMTypeName; + ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } +} +export class FSMSendMsg extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} +export class GZ0 extends OBInstruction { + VarType; + VarIdx; + ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } +} + +export class BRIF extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } +} +export class DEC extends OBInstruction { + regType; + regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + let v = LongReg(st, uf, locals); + return v - 1; + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + let v = DoubleReg(st, uf, locals); + return v - 1; + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } +} +export class Reg2Var extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } +} +export class Var2Reg extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } +} +export class I2F extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } +} +export class EQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class NEQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class LT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class LTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class GT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } +} + +export class GTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } +} +export class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } +} +export class FSMBroadcastMsg extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} + +/** + * 单元数操作 + */ +export class SGLF extends OBInstruction { + Opcode; + value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } +} +export class RAND extends OBInstruction { + Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } +} +export class F2I extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } +} +export class FSMSendMsgWait_Data extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } +} +export class FSMSendMsgWait extends OBInstruction { + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } +} +export class FSMBroadcastMsgWait extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } +} +export class TextJoin extends OBInstruction { + Left; + Right; + RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } +} +export class ToString extends OBInstruction { + ValueType; + ValueRegIdx; + RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } +} +export class Sender extends OBInstruction { + RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } +} +export class SHL extends OBInstruction { + value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } +} +export class AND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } +} +export class FIX extends OBInstruction { + regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } +} +/** + * value of may by key + */ +export class VOM extends OBInstruction { + map; + key; + ValueType; + RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } +} +export class LAND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } +} +export class LOR extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 1 : 0; + } + }; + } +} +export class LNOT extends OBInstruction { + a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } +} +export class COND extends OBInstruction { + if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } +} +export class NEW extends OBInstruction { + StructDef; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFF0000) >> 16; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } +} diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.hml b/hap/entry/src/main/js/MainAbility/pages/index/index.hml index f4ed250..3c7fc8e 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.hml +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.hml @@ -19,14 +19,14 @@ -->
- - - +
+ {{ info }} +
- +
\ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index e317d75..0a7e97d 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -17,6 +17,7 @@ import fileio from '@ohos.fileio'; import * as obvm from '../../common/runtime/vm.js'; import * as obcanvaslib from '../../common/canvas.js' import prompt from '@system.prompt'; +import app from '@system.app'; let filepath = '/data/openblock.xe'; export default { @@ -33,7 +34,7 @@ export default { }] }, log(s) { - this.info = s; + this.info +="\n"+ s; }, ob_event(name) { this.log(name); @@ -68,31 +69,42 @@ export default { initStage() { let stage = this.$refs.canvas1; try { + filepath = "/data/"+app.getInfo().appID+"/main.xe"; + this.log(filepath); stage.width = stage.width; let fd = fileio.openSync(filepath, 0o2); let st = fileio.fstatSync(fd); + this.log('a'); let scriptArrayBuffer = new ArrayBuffer(st.size); fileio.readSync(fd, scriptArrayBuffer); + this.log('b'); let obcanvas = new obcanvaslib.OBCanvas2D(stage); // let ctx = stage.getContext('2d'); // ctx.fillRect(15, 15, 50, 50); + this.log('c'); let nativeLibs = [obcanvas.install.bind(obcanvas)]; let loader = obvm.OBScriptLoader; let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); + this.log('d'); this.vm = new obvm.OBVM(loadedScript); + this.log('e'); // // vm.Output = alert.bind(window); - this.vm.Output = prompt.showToast; + this.vm.Output = this.log;//prompt.showToast; let fsmname = 'Start.Main'; let fsm = this.vm.CreateFSM(fsmname); + this.log('f'); if (!fsm) { + this.log('no fsm'); throw Error("No FSM named " + fsmname); } + this.log('g'); this.fsm = fsm; } catch (e) { - this.info = "\nERROR:" + e.toString(); + this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); } finally { + this.log('h'); } }, onActive() { @@ -104,6 +116,7 @@ export default { this.fileCheckInterval = setInterval(this.checkFile, 3000); }, checkFile() { + this.log("1"); let fd = fileio.openSync(filepath, 0o2); let stat = fileio.fstatSync(fd); let ctime = stat.ctime; @@ -113,14 +126,19 @@ export default { this.filectime = ctime; this.initStage(); } + this.log("2"); }, onInactive() { clearInterval(this.updateInterval); clearInterval(this.fileCheckInterval); }, update() { - if (this.vm) { - this.vm.update(); + try { + if (this.vm) { + this.vm.update(); + } + }catch(e){ + this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); } }, onchange(type) { -- Gitee From 54fba0dffe1a557e37eafeda4b10cf2403a5735c Mon Sep 17 00:00:00 2001 From: duzc2 Date: Wed, 2 Mar 2022 23:02:16 +0800 Subject: [PATCH 16/30] update vm --- .../src/main/js/MainAbility/common/canvas.js | 4 +++- .../main/js/MainAbility/common/runtime/vm.js | 14 ++++++++--- .../main/js/MainAbility/pages/index/index.js | 23 +++++++++++++------ 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index 09c486d..5d966ad 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -68,7 +68,7 @@ export class OBCanvas2D { script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), @@ -85,6 +85,8 @@ export class OBCanvas2D { script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), ]); } } \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 9b77986..c1971e6 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -1466,6 +1466,7 @@ export class OBVM { * @1type {function(any)} */ Output; + setTimeout; /** * typeName->[VMFSM] * @1type {Object.} @@ -1483,11 +1484,17 @@ export class OBVM { * * @param {OBScript} script */ - constructor(script) { + constructor(script,config) { if (!script) { throw Error("Script is null"); } this.script = script; + if(config){ + Object.assign(this,config); + } + if(!this.setTimeout){ + this.setTimeout = setTimeout; + } } CreateFSM(name) { @@ -1576,7 +1583,7 @@ export class OBVM { * @param {*} callback */ Schedule(millisecond, callback) { - setTimeout(callback, millisecond, this); + this.setTimeout(callback, millisecond, this); } FindRunningFSMByType(typeFullName) { @@ -1788,7 +1795,8 @@ export class OBVMState { let h = this.data.EventHandlers[msg.name]; if (h) { this.currentMessage = msg; - new OBVMFunction(h.Func).Call(this); + let vmf = new OBVMFunction(h.Func); + vmf.Call(this); } } finally { this.currentMessage = null; diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index 0a7e97d..75c323b 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -85,10 +85,15 @@ export default { this.log('c'); let nativeLibs = [obcanvas.install.bind(obcanvas)]; + this.log('c1'); let loader = obvm.OBScriptLoader; + this.log('c2'); let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); this.log('d'); - this.vm = new obvm.OBVM(loadedScript); + this.vm = new obvm.OBVM(loadedScript,{setTimeout:setTimeout}); + this.vm.setTimeout(()=>{ + this.log('setTimeout'); + },1); this.log('e'); // // vm.Output = alert.bind(window); this.vm.Output = this.log;//prompt.showToast; @@ -108,12 +113,14 @@ export default { } }, onActive() { - if (this.uninited) { - this.uninited = false; - this.initStage(); - } - this.updateInterval = setInterval(this.update, 30); - this.fileCheckInterval = setInterval(this.checkFile, 3000); + setTimeout(()=>{ + if (this.uninited) { + this.uninited = false; + this.initStage(); + } + this.updateInterval = setInterval(this.update, 30); + this.fileCheckInterval = setInterval(this.checkFile, 3000); + },1); }, checkFile() { this.log("1"); @@ -135,7 +142,9 @@ export default { update() { try { if (this.vm) { + this.log('u1'); this.vm.update(); + this.log('u2'); } }catch(e){ this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); -- Gitee From 84da269aa51a2f80872afc8bf7e87e9c426c7628 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Mon, 7 Mar 2022 20:31:04 +0800 Subject: [PATCH 17/30] 1 --- .../src/main/js/MainAbility/common/canvas.js | 1 + .../main/js/MainAbility/common/runtime/vm.js | 17 +++++++++++++ .../main/js/MainAbility/pages/index/index.js | 20 ++++----------- .../js/MainAbility/pages/second/second.css | 6 +---- .../js/MainAbility/pages/second/second.hml | 4 +-- .../js/MainAbility/pages/second/second.js | 25 ++++++++++++++++--- 6 files changed, 47 insertions(+), 26 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index 5d966ad..e71acf5 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -40,6 +40,7 @@ export class OBCanvas2D { this.canvas2dctx.fillStyle = str_color.substr(0, 7); } setStrokeStyleColor(color) { + throw 'setStrokeStyleColor'; let str_color; if (color < 0) { str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index c1971e6..4061e0c 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -57,8 +57,14 @@ export class NativeUtil { }; }); builder.PushAction((st, f, local, pos) => { + st.fsm.VM.Log('native func') let argVals = argGetters.map(g => g(st, f, local)); + st.fsm.VM.Log('native func1') + st.fsm.VM.Log(func) + st.fsm.VM.Log(JSON.stringify(argVals)); + func.apply(null, argVals); + st.fsm.VM.Log('native func2') return pos + 1; }); }; @@ -541,6 +547,9 @@ export class OBFunctionBuilder { } PushAction(Instruction) { + if(!Instruction){ + throw 'Instruction is null,1'; + } let stmt = this.RootStatementContext; let newPos = stmt.Actions.length; stmt.PushAction(Instruction); @@ -1450,6 +1459,9 @@ export class OBStatementContext { Actions = []; PushAction(Instruction) { + if(!Instruction){ + throw 'Instruction is null,2'; + } this.Actions.push(Instruction); } } @@ -1956,8 +1968,13 @@ export class OBVMFunction { } } let Actions = this.data.Statements.Actions; + state.fsm.VM.Log(JSON.stringify(Actions)); for (let i = 0; i < Actions.length && i >= 0;) { let action = Actions[i]; + if(!action){ + throw 'action is null' + } + state.fsm.VM.Log(action); i = action(state, this, this.LocalVar, i); } } diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index 75c323b..3c9d440 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -74,29 +74,19 @@ export default { stage.width = stage.width; let fd = fileio.openSync(filepath, 0o2); let st = fileio.fstatSync(fd); - this.log('a'); let scriptArrayBuffer = new ArrayBuffer(st.size); fileio.readSync(fd, scriptArrayBuffer); - this.log('b'); let obcanvas = new obcanvaslib.OBCanvas2D(stage); // let ctx = stage.getContext('2d'); // ctx.fillRect(15, 15, 50, 50); - this.log('c'); let nativeLibs = [obcanvas.install.bind(obcanvas)]; - this.log('c1'); let loader = obvm.OBScriptLoader; - this.log('c2'); let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); - this.log('d'); - this.vm = new obvm.OBVM(loadedScript,{setTimeout:setTimeout}); - this.vm.setTimeout(()=>{ - this.log('setTimeout'); - },1); - this.log('e'); + this.vm = new obvm.OBVM(loadedScript,{setTimeout:setTimeout,Output:this.log}); // // vm.Output = alert.bind(window); - this.vm.Output = this.log;//prompt.showToast; +// this.vm.Output = this.log;//prompt.showToast; let fsmname = 'Start.Main'; let fsm = this.vm.CreateFSM(fsmname); this.log('f'); @@ -104,7 +94,6 @@ export default { this.log('no fsm'); throw Error("No FSM named " + fsmname); } - this.log('g'); this.fsm = fsm; } catch (e) { this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); @@ -123,7 +112,6 @@ export default { },1); }, checkFile() { - this.log("1"); let fd = fileio.openSync(filepath, 0o2); let stat = fileio.fstatSync(fd); let ctime = stat.ctime; @@ -133,13 +121,15 @@ export default { this.filectime = ctime; this.initStage(); } - this.log("2"); }, onInactive() { clearInterval(this.updateInterval); clearInterval(this.fileCheckInterval); }, update() { + if(this.info.length > 50){ + return; + } try { if (this.vm) { this.log('u1'); diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.css b/hap/entry/src/main/js/MainAbility/pages/second/second.css index 31a3676..5a91124 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/second.css +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.css @@ -10,11 +10,7 @@ } .title { - font-size: 60px; - text-align: center; - width: 100%; - height: 40%; - margin: 10px; + font-size: 30px; } .btn { diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.hml b/hap/entry/src/main/js/MainAbility/pages/second/second.hml index d75ce93..0a0d321 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/second.hml +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.hml @@ -1,6 +1,6 @@
+ - {{ $t('strings.page') }} + {{info}} -
diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.js b/hap/entry/src/main/js/MainAbility/pages/second/second.js index ac4f4f8..9d55278 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/second.js +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.js @@ -2,11 +2,28 @@ import router from '@system.router' export default { data: { - title: 'World' + info: 'World' + }, + log(s) { + this.info +="\n"+ s; }, onclick: function () { - router.replace({ - uri: "pages/index/index" - }) + this.log('0'); + try { + this.log('1'); + function f(v,w){ + this.log(v); + this.log(w); + } + let tf = [f.bind(this)]; + setTimeout(()=>{ + tf[0].apply(null,['4','5']); + },100); + tf[0].apply(null,['2','3']); + } catch (e) { + this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); + } finally { + this.log('h'); + } } } -- Gitee From da523fe9e97fc07b4b5a91b2514207ba1e208a1b Mon Sep 17 00:00:00 2001 From: duzc2 Date: Wed, 9 Mar 2022 14:34:30 +0800 Subject: [PATCH 18/30] 1 --- hap/build.gradle | 6 ++--- hap/entry/build.gradle | 4 ++-- hap/entry/src/main/config.json | 2 +- .../main/js/MainAbility/common/runtime/vm.js | 18 ++++---------- .../main/js/MainAbility/pages/index/index.hml | 2 +- .../main/js/MainAbility/pages/index/index.js | 24 +++++++++++++++---- .../js/MainAbility/pages/second/second.js | 13 ++++++++++ 7 files changed, 45 insertions(+), 24 deletions(-) diff --git a/hap/build.gradle b/hap/build.gradle index c2c8bba..f1b1a55 100644 --- a/hap/build.gradle +++ b/hap/build.gradle @@ -3,7 +3,7 @@ apply plugin: 'com.huawei.ohos.app' //For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 ohos { - compileSdkVersion 7 + compileSdkVersion 8 supportSystem "standard" } @@ -17,8 +17,8 @@ buildscript { } } dependencies { - classpath 'com.huawei.ohos:hap:3.0.3.4' - classpath 'com.huawei.ohos:decctest:1.2.6.0' + classpath 'com.huawei.ohos:hap:3.0.5.2' + classpath 'com.huawei.ohos:decctest:1.2.7.2' } } diff --git a/hap/entry/build.gradle b/hap/entry/build.gradle index 316c1ea..92a548d 100644 --- a/hap/entry/build.gradle +++ b/hap/entry/build.gradle @@ -12,9 +12,9 @@ ohos { // certpath file('C:\\openharmony\\key1\\openharmony.cer') // } // } - compileSdkVersion 7 + compileSdkVersion 8 defaultConfig { - compatibleSdkVersion 7 + compatibleSdkVersion 8 } buildTypes { release { diff --git a/hap/entry/src/main/config.json b/hap/entry/src/main/config.json index b26e079..787cc5f 100644 --- a/hap/entry/src/main/config.json +++ b/hap/entry/src/main/config.json @@ -53,7 +53,7 @@ ], "name": ".MainAbility", "window": { - "designWidth": 720, + "designWidth": 750, "autoDesignWidth": false } } diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 4061e0c..3f36218 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -57,14 +57,12 @@ export class NativeUtil { }; }); builder.PushAction((st, f, local, pos) => { - st.fsm.VM.Log('native func') let argVals = argGetters.map(g => g(st, f, local)); - st.fsm.VM.Log('native func1') - st.fsm.VM.Log(func) - st.fsm.VM.Log(JSON.stringify(argVals)); - - func.apply(null, argVals); - st.fsm.VM.Log('native func2') + try { + func.apply(null,argVals); + }catch(e){ + st.fsm.VM.Log('Error: '+e+" "+func.name); + } return pos + 1; }); }; @@ -1579,7 +1577,6 @@ export class OBVM { * @param {OBUserMessage} userMessage */ BroadcastMessage(userMessage) { - this.Output('BroadcastMessage'); Object.values(this.Running).forEach(l => { for (let i = 0; i < l.length; i++) { let f = l[i]; @@ -1968,13 +1965,8 @@ export class OBVMFunction { } } let Actions = this.data.Statements.Actions; - state.fsm.VM.Log(JSON.stringify(Actions)); for (let i = 0; i < Actions.length && i >= 0;) { let action = Actions[i]; - if(!action){ - throw 'action is null' - } - state.fsm.VM.Log(action); i = action(state, this, this.LocalVar, i); } } diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.hml b/hap/entry/src/main/js/MainAbility/pages/index/index.hml index 3c7fc8e..93bfda8 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.hml +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.hml @@ -26,7 +26,7 @@ ontouchmove="ob_touchmove" ontouchcancel="ob_touchcancel" ontouchend="ob_touchend" onlongpress="ob_longpress" onclick="ob_click"> - + \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index 3c9d440..91087e4 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -20,6 +20,26 @@ import prompt from '@system.prompt'; import app from '@system.app'; let filepath = '/data/openblock.xe'; +// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js +// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart +if (!String.prototype.padStart) { + String.prototype.padStart = function padStart(targetLength,padString) { + targetLength = targetLength>>0; //floor if number or convert non-number to 0; + padString = String((typeof padString !== 'undefined' ? padString : ' ')); + if (this.length > targetLength) { + return String(this); + } + else { + targetLength = targetLength-this.length; + if (targetLength > padString.length) { + padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed + } + return padString.slice(0,targetLength) + String(this); + } + }; +} + + export default { data: { info: "info:", @@ -89,7 +109,6 @@ export default { // this.vm.Output = this.log;//prompt.showToast; let fsmname = 'Start.Main'; let fsm = this.vm.CreateFSM(fsmname); - this.log('f'); if (!fsm) { this.log('no fsm'); throw Error("No FSM named " + fsmname); @@ -98,7 +117,6 @@ export default { } catch (e) { this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); } finally { - this.log('h'); } }, onActive() { @@ -132,9 +150,7 @@ export default { } try { if (this.vm) { - this.log('u1'); this.vm.update(); - this.log('u2'); } }catch(e){ this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.js b/hap/entry/src/main/js/MainAbility/pages/second/second.js index 9d55278..32b3abd 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/second.js +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.js @@ -1,4 +1,5 @@ import router from '@system.router' +import fetch from '@system.fetch'; export default { data: { @@ -9,6 +10,18 @@ export default { }, onclick: function () { this.log('0'); + try{ + fetch.fetch({ + url: 'http://122.9.129.166:1918/login/', + method: "POST", + data: { + uid: '123', + pwd: '123', + }}); + }catch(e){ + this.log("\n fetch ERROR:"+e.toString()+"\n" + JSON.stringify(e)); + return; + } try { this.log('1'); function f(v,w){ -- Gitee From 640d6bd358950273f5fea73a054516b60a6c34c6 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Wed, 9 Mar 2022 15:31:39 +0800 Subject: [PATCH 19/30] update vm Signed-off-by: duzc2 --- .../main/js/MainAbility/common/runtime/vm.js | 8712 +++++++++-------- 1 file changed, 4366 insertions(+), 4346 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 3f36218..c04ae6c 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -3,4349 +3,4369 @@ * Copyright 2021 Du Tian Wei * SPDX-License-Identifier: Apache-2.0 */ -import * as util from './util.js' -export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - static objFieldGetter(fieldName, fieldRegister) { - return (builder, args) => { - let obj = builder.NObjectRegister[args[1] & 0xfff]; - builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { - return obj(st, f, local)[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureVoid(func, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - if (typeof (v) != 'function') { - debugger - } - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - try { - func.apply(null,argVals); - }catch(e){ - st.fsm.VM.Log('Error: '+e+" "+func.name); - } - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); - }); - }; - return f; - } -} -export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @1type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {number} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } -} -export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int -} -export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; -} -export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } -} -export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; -} -export class OBCodeSegment { - name; - functions; - fsms; -} -export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - Statements; -} -export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - /** - * @type {string} - */ - ModuleName; -} -export class OBMessageHandler { - Name; - Func; - ArgTypeName; -} -export class OBEventHandler { - Name; - Func; -} -export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } -} -export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - throw Error("Unknown byte code command:" + cmd); - case 9: - throw Error("Unknown byte code command:" + cmd); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - case 59: - return new NEW(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } -} -export class PositionUpdatePair { - targetOffset; - callback; -} -export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - RootStatementContext = new OBStatementContext(); //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {OBStructValue} - */ - /** - * @type {Array} StructRegister[] - */ - StructRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {object} - */ - /** - * @type {Array} NObjectRegister[] - */ - NObjectRegister; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - // this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - varInfo[i] = info; - } - this.StatementLength = reader.ReadUInt32(); - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - if(!Instruction){ - throw 'Instruction is null,1'; - } - let stmt = this.RootStatementContext; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset === this.currentInstructPosition) { - p.callback(newPos); - } - }); - } -} - -export class OBBuildInFunctions { - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward === 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let typename = a2(state, func, locals); - let id = a1(state, func, locals); - let r = StructData.Get(typename, id); - if(!r){ - throw `Can't find ${typename} which id is ${id}`; - } - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } -} -export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(null); - registers.LongRegister = []; - registers.LongRegister.fill(0, 0, Def.IntegerCnt); - registers.DoubleRegister = []; - registers.DoubleRegister.fill(0, 0, Def.FloatCnt); - registers.StringRegister = []; - registers.StringRegister.fill('', 0, Def.StringCnt); - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } -} -export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @1param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - if (type.startsWith("S") && type.endsWith(";")) { - type = type.substr(1, type.length - 2); - } - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - let def = this.StructDef[type]; - let group = this.Groups[type]; - if(!group){ - throw `There is no preset data of the type ${type}`; - } - let reader = group.Data; - let itemStart = 0; - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid === id) { - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - } - throw Error("找不到 ID为" + id + "的" + type); - } -} - -export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBufferReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let _length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } -} -class Relocation { - /** - * @1type {Object.:{idx:Number,inited:bool}>} - */ - string = {}; - /** - * @1type {Object.} - */ - integer = {}; - /** - * @1type {Object.} - */ - float = {}; - /** - * @1type {Object.} - */ - bin = {}; - /** - * @1type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } -} -export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadUInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadUInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadUInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw Error("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - let length = SegmentReader.ReadUInt32(); - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName === s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - // let typeIdx = reader.ReadUInt32(); - // let count = reader.ReadInt32(); - let vari = reader.ReadUInt32(); - let count = vari & 0xFFFFFFF; - let typeIdx = vari >> 28; - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadUInt32(); - let d = {}; - let cnt = reader.ReadUInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadUInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadUInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadUInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } -} - -export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {Number} integer of start - */ - start; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.start = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(this.start + p, true); - // let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(this.start + p, true); - // let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(this.start + p, true); - // let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let str = this.stringCache[stringIdx]; - if (str) { - return str; - } - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(this.start + start, true); - if (length === 0) { - return ""; - } - start = this.start + start + 4; - // start = start + 4; - let ab = this.buf.slice(start, start + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - str = utf8decoder.decode(ui8); - if (str === null) { - throw Error('no string value of idx:' + stringIdx); - } - this.stringCache[stringIdx] = str; - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - // let buf; - // if (typeof (length) === "undefined") { - // buf = this.buf.slice(pos); - // } else { - // buf = this.buf.slice(pos, pos + length); - // } - // let reader = new OBArrayBufferReader(buf); - // reader.start = this.start + pos; - // return reader; - let reader = new OBArrayBufferReader(this.buf); - reader.start = this.start + pos; - return reader; - } - - seek(pos) { - if (typeof (pos) === "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } -} - - -export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - if(!Instruction){ - throw 'Instruction is null,2'; - } - this.Actions.push(Instruction); - } -} -// 虚拟机 - -export class VMInterruptException { -} -export class ChangeStateException extends VMInterruptException { -} -export class ChangeDestroyException extends VMInterruptException { -} -export class OBVM { - /** - * @1type {function(any)} - */ - Output; - setTimeout; - /** - * typeName->[VMFSM] - * @1type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @1type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script,config) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - if(config){ - Object.assign(this,config); - } - if(!this.setTimeout){ - this.setTimeout = setTimeout; - } - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - // let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f === fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {*} callback - */ - Schedule(millisecond, callback) { - this.setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } -} -export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - if (!this.CurrentState) { - return; - } - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.data.Name); - } - } -} -export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.LongRegister = []; - this.LongRegister.length = v.count; - this.LongRegister.fill(0); - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.DoubleRegister = []; - this.DoubleRegister.length = v.count; - this.DoubleRegister.fill(0); - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StringRegister = []; - this.StringRegister.length = v.count; - this.StringRegister.fill(""); - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StructRegister = []; - this.StructRegister.length = v.count; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.NObjectRegister = []; - this.NObjectRegister.length = v.count; - break; - default: - throw Error("Unknown type " + v.typeIdx); - } - }); - } -} -export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {OBTypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let h = this.data.EventHandlers[msg.name]; - if (h) { - this.currentMessage = msg; - let vmf = new OBVMFunction(h.Func); - vmf.Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let hl = this.data.MessageHandlers[m.name]; - if (hl) { - hl.forEach(h => { - if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { - new OBVMFunction(h.Func).Call(this); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } -} -export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {OBTypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc, builder, args) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - if (builder) { - /** - * @1type {List>();} - */ - let LongRegister_ = []; - let DoubleRegister_ = [];// new List>(); - let StringRegister_ = [];// new List>(); - let StructRegister_ = [];// new List>(); - let NObjectRegister_ = [];//new List>(); - - for (let i = 1; i < args.length; i++) { - let arg = args[i]; - let Register = arg & 0xFFF; - let RegisterType = (arg >> 12) & 0xF; - - switch (RegisterType) { - case 0: - LongRegister_.push(builder.LongRegister[Register]); - break; - case 1: - DoubleRegister_.push(builder.DoubleRegister[Register]); - break; - case 2: - StringRegister_.push(builder.StringRegister[Register]); - break; - case 3: - StructRegister_.push(builder.StructRegister[Register]); - break; - case 4: - NObjectRegister_.push(builder.NObjectRegister[Register]); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - if (LongRegister_.length > 0) { - this.LongRegister = LongRegister_; - } - if (DoubleRegister_.length > 0) { - this.DoubleRegister = DoubleRegister_; - } - if (StringRegister_.length > 0) { - this.StringRegister = StringRegister_; - } - if (StructRegister_.length > 0) { - this.StructRegister = StructRegister_; - } - if (NObjectRegister_.length > 0) { - this.NObjectRegister = NObjectRegister_; - } - } - } - /** - * - * @param {OBVMState} state - */ - Call(state, uBFunction, localVars) { - if (uBFunction) { - if (this.LongRegister != null) { - for (let i = 0; i < this.LongRegister.length; i++) { - this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); - } - } - if (this.DoubleRegister != null) { - for (let i = 0; i < this.DoubleRegister.length; i++) { - this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); - } - } - if (this.StringRegister != null) { - for (let i = 0; i < this.StringRegister.length; i++) { - this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); - } - } - if (this.StructRegister != null) { - for (let i = 0; i < this.StructRegister.length; i++) { - this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); - } - } - if (this.NObjectRegister != null) { - for (let i = 0; i < this.NObjectRegister.length; i++) { - this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); - } - } - } - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType === 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType === 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType === 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType === 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType === 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } -} -export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return arg.Def.Name; - case 4: - // return "NObject"; - if (arg.constructor === OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } -} -export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } -} -export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - console.error(err); - throw err; - } - } - } -} -// 字节码 -export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } -} -export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } -} -export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } -} -export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } -} -export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } -} -export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } -} -export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } -} -export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } -} -export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } -} -export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } -} -export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } -} -export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } -} -export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } -} -export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister === -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } -} -export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - targetOffsetBak; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - this.targetOffsetBak = this.targetOffset; - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } -} -export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } -} -export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } -} -export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } -} - -export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } -} -export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } -} -export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFFF; - switch (specal) { - case 0xFFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } -} -export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } -} -export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } -} -export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } else { - fsm.Target = st.fsm.Target; - } - return fsm; - }; - } -} -export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} -export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } -} - -export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } -} -export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - let v = LongReg(st, uf, locals); - return v - 1; - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - let v = DoubleReg(st, uf, locals); - return v - 1; - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } -} -export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } -} -export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } -} -export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } -} -export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } -} - -export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } -} -export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} - -/** - * 单元数操作 - */ -export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } -} -export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } -} -export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } -} -export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } -} -export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } -} -export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} -export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } -} -export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } -} -export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } -} -export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } -} -export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } -} -export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } -} -/** - * value of may by key - */ -export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } -} -export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return c ? 1 : 0; - } else { - return 0; - } - }; - } -} -export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return c ? 1 : 0; - } - }; - } -} -export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return v === 0 ? 1 : 0; - }; - } -} -export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } -} -export class NEW extends OBInstruction { - StructDef; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Register = (code & 0xFF0000) >> 16; - - let structType = builder.loader.data.GetString(stridx); - let structDef = builder.loader.script.StructDef[structType]; - if (!structDef) { - throw Error('不存在数据结构 ' + structType); - } - this.StructDef = structDef; - } - - link(builder, instructions, idx) { - builder.StructRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - let s = new OBStructValue(this.StructDef); - return s; - } -} + import * as util from './util.js' + export class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + static objFieldGetter(fieldName, fieldRegister) { + return (builder, args) => { + let obj = builder.NObjectRegister[args[1] & 0xfff]; + builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { + return obj(st, f, local)[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + if (typeof (v) != 'function') { + debugger + } + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + try { + func.apply(null, argVals); + } catch (e) { + st.fsm.VM.Log('Error: ' + e + " " + func.name); + } + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + try { + return func.apply(null, argVals); + } catch (e) { + st.fsm.VM.Log('Error: ' + e + " " + func.name); + throw e; + } + }); + }; + return f; + } + } + export class OBScript { + NativeLibHash = {}; // libname->hash + InstalledLibs = {}; + NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + StructDef = {}; // typename-> def + loadedFunctions; //= {};//function sign->function + FullNameFSMData = {}; //FullName->OBFSM + + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } + } + export class OBStructDef { + Name; //string + StructCnt; // int + StringCnt; // int + IntegerCnt; // int + FloatCnt; // int + NobjectCnt; // int + StructFields; // int + } + export class OBStructValueData { + /** + * @type {OBArrayBufferReader} + */ + Data; //arraybuffer + FullName; + Offset; + Length; + StructCount; + } + export class OBVariableInfo { + typeIdx; + count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } + } + export class OBState { + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + Name; + MessageHandlers; + EventHandlers; + } + export class OBCodeSegment { + name; + functions; + fsms; + } + export class OBFunction { + /** + * @type {OBVariableInfo[]} + */ + Variables; + instructions; + /** + * @type {String} + */ + Signure; + Statements; + } + export class OBFSM { + /** + * @type {string} + */ + Name; + /** + * @type {Object.} + */ + States; //string->state + /** + * @type {OBState} + */ + Entry; //state + /** + * @type {OBVariableInfo[]} + */ + Variables; + /** + * @type {string} + */ + FullName; + /** + * @type {string} + */ + ModuleName; + } + export class OBMessageHandler { + Name; + Func; + ArgTypeName; + } + export class OBEventHandler { + Name; + Func; + } + export class OBInstruction { + Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } + } + export class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + throw Error("Unknown byte code command:" + cmd); + case 9: + throw Error("Unknown byte code command:" + cmd); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } + } + export class PositionUpdatePair { + targetOffset; + callback; + } + export class OBFunctionBuilder { + loader; //OBScriptLoader + StatementLength; //integer + BuildingFunc; //OBFunction + PositionUpdatePairList; + currentInstructPosition; //integer + RootStatementContext = new OBStatementContext(); //[StatementContext] + + /** + * @callback LongRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type LongRegister[] + */ + LongRegister; + /** + * @callback DoubleRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {number} + */ + /** + * @type DoubleRegister[] + */ + DoubleRegister; + /** + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {string} + */ + /** + * @type StringRegister[] + */ + StringRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {OBStructValue} + */ + /** + * @type {Array} StructRegister[] + */ + StructRegister; + /*@ + * @callback StringRegister + * @param {OBVMState} + * @param {OBFunctionBuilder} + * @param {OBInstruction[]} + * @returns {object} + */ + /** + * @type {Array} NObjectRegister[] + */ + NObjectRegister; + + constructor(loader) { + this.loader = loader; + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + // this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + this.StatementLength = reader.ReadUInt32(); + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.RootStatementContext; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } + } + + export class OBBuildInFunctions { + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let typename = a2(state, func, locals); + let id = a1(state, func, locals); + let r = StructData.Get(typename, id); + if (!r) { + throw `Can't find ${typename} which id is ${id}`; + } + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } + } + export class OBStructValue { + /** + * @type {OBStructDef} + */ + Def; + /** + * @type {OBTypedVariableGroup} + */ + registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } + } + export class StructData { + /** + * @type {Object.} + */ + StructDef; + /** + * @type {Object.} + */ + Groups; + /** + * @type {OBArrayBufferReader} + */ + DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + if (!group) { + throw `There is no preset data of the type ${type}`; + } + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } + } + + export class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let _length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } + } + class Relocation { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + string = {}; + /** + * @1type {Object.} + */ + integer = {}; + /** + * @1type {Object.} + */ + float = {}; + /** + * @1type {Object.} + */ + bin = {}; + /** + * @1type {Object.} + */ + structFieldIndex = {}; + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } + } + export class OBScriptLoader { + /** + * @type {OBArrayBufferReader} + */ + reader; //OBArrayBufferReader + /** + * @type {OBArrayBufferReader} + */ + data; //OBArrayBufferReader + loadingFunctions = {}; //[OBFunctionBuilder] + Linkings = []; //Linkable + + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadUInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadUInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadUInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + let length = SegmentReader.ReadUInt32(); + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + // let typeIdx = reader.ReadUInt32(); + // let count = reader.ReadInt32(); + let vari = reader.ReadUInt32(); + let count = vari & 0xFFFFFFF; + let typeIdx = vari >> 28; + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadUInt32(); + let d = {}; + let cnt = reader.ReadUInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadUInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadUInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadUInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } + } + + export class OBArrayBufferReader { + /** + * @type {Number} integer of position + */ + pos; // int + /** + * @type {Number} integer of start + */ + start; // int + /** + * @type {ArrayBuffer} + */ + buf; // ArrayBuffer + /** + * @type DataView + */ + view; // DataView + /** + * @type {Object.} + */ + stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.start = 0; + this.view = new DataView(buf); + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(this.start + p, true); + // let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(this.start + p, true); + // let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(this.start + p, true); + // let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let str = this.stringCache[stringIdx]; + if (str) { + return str; + } + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(this.start + start, true); + if (length === 0) { + return ""; + } + start = this.start + start + 4; + // start = start + 4; + let ab = this.buf.slice(start, start + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + this.stringCache[stringIdx] = str; + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + // let buf; + // if (typeof (length) === "undefined") { + // buf = this.buf.slice(pos); + // } else { + // buf = this.buf.slice(pos, pos + length); + // } + // let reader = new OBArrayBufferReader(buf); + // reader.start = this.start + pos; + // return reader; + let reader = new OBArrayBufferReader(this.buf); + reader.start = this.start + pos; + return reader; + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } + } + + + export class OBStatementContext { + InstPos; + Actions = []; + + PushAction(Instruction) { + this.Actions.push(Instruction); + } + } + // 虚拟机 + + export class VMInterruptException { + } + export class ChangeStateException extends VMInterruptException { + } + export class ChangeDestroyException extends VMInterruptException { + } + export class OBVM { + /** + * @1type {function(any)} + */ + Output; + setTimeout; + /** + * typeName->[VMFSM] + * @1type {Object.} + */ + Running = {}; + /** + * @type OBScript + */ + script; + /** + * @1type {OBVMFSM} + */ + Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script, config) { + if (!script) { + throw Error("Script is null"); + } + this.script = script; + if (config) { + Object.assign(this, config); + } + if (!this.setTimeout) { + this.setTimeout = setTimeout.bind(window); + } + } + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + // let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + this.setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } + } + export class OBVMFSM { + static ID_GEN = 0; + Running = true; + OnDestroyedCallbacks = []; + /** + * @type {any} + */ + Target; + /** + * @type {OBFSM} + */ + data; + id; + /** + * @type {OBVMState} + */ + CurrentState; + /** + * @type {OBVMState[]} + */ + StateStack = []; + /** + * @type {OBVM} + */ + VM; + Inbox = []; + PrioritizedInbox = []; + VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.data = data; + this.id = ++OBVMFSM.ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + if (!this.CurrentState) { + return; + } + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + OnDestroyed(f) { + this.OnDestroyedCallbacks.push(f); + } + OffDestroyed(f) { + let idx = this.OnDestroyedCallbacks.indexOf(f); + if (idx >= 0) { + this.OnDestroyedCallbacks.slice(idx, 1); + } + } + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + this.Running = false; + this.OnDestroyedCallbacks.forEach(f => { + f(this); + }); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } + } + export class OBTypedVariableGroup { + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } + } + export class OBVMState { + /** + * @type {OBState} + */ + data; + /** + * @type {OBVMFSM} + */ + fsm; + /** + * @type {OBTypedVariableGroup} + */ + VariableGroup; + /** + * @type {OBMessage} + */ + currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } + } + export class OBVMFunction { + /** + * @type {OBFunction} + */ + data; + /** + * @type {OBTypedVariableGroup} + */ + LocalVar; + returnType = -1; + returnValue; + LongRegister; + DoubleRegister; + StringRegister; + StructRegister; + NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } + } + export class OBMessage { + name; + arg; + argType; + sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } + } + export class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } + } + export class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + console.error(err); + throw err; + } + } + } + } + // 字节码 + export class LDSTR extends OBInstruction { + Value; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } + } + export class PRT extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } + } + export class ReceivedMessage extends OBInstruction { + typeId; + Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } + } + export class STVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + export class STVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + export class StructFieldDesc extends OBInstruction { + fieldTypeId; + fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } + } + export class GetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + let v = stt.registers.LongRegister[fieldIdx]; + if (typeof (v) != 'number') { + console.log('wrong') + } + return v; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + export class SetStructField extends OBInstruction { + structIdx; + Register; + typeId; + fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let dr = getStruct(st, uf, locals).registers.DoubleRegister; + if (dr.length <= fieldIdx) { + throw Error('fieldIdx wrong') + } + dr[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + export class CHSTT extends OBInstruction { + StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } + } + export class MethodCallRegisterInfoAnchor extends OBInstruction { + RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } + } + export class NativeMethodCall extends OBInstruction { + LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } + } + export class FSMVS extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + export class SLF extends OBInstruction { + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } + } + export class MethodCall extends OBInstruction { + MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } + } + export class BRIFN extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + targetOffsetBak; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffsetBak = this.targetOffset; + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } + } + export class BR extends OBInstruction { + Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } + } + export class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } + } + export class ARITHF extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } + } + + export class ARITHI extends OBInstruction { + Opcode; + LeftRegister; + RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } + } + export class LDI extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } + } + export class LDF extends OBInstruction { + Register; + Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFFF; + switch (specal) { + case 0xFFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } + } + export class RET extends OBInstruction { + RegisterType; + RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } + } + export class FSMVG extends OBInstruction { + Register; + VarIdx; + RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + export class CreateFSM extends OBInstruction { + FSMTypeName; + ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } + } + export class FSMSendMsg extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + export class GZ0 extends OBInstruction { + VarType; + VarIdx; + ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } + } + + export class BRIF extends OBInstruction { + checkRegType; + checkRegIdx; + targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } + } + export class DEC extends OBInstruction { + regType; + regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + let v = LongReg(st, uf, locals); + return v - 1; + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + let v = DoubleReg(st, uf, locals); + return v - 1; + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } + } + export class Reg2Var extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + export class Var2Reg extends OBInstruction { + type; + varIdx; + regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + export class I2F extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } + } + export class EQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class NEQ extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class LT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class LTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class GT extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + + export class GTE extends OBInstruction { + ArgTypeId; + LeftIdx; + RightIdx; + RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + export class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } + } + export class FSMBroadcastMsg extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + + /** + * 单元数操作 + */ + export class SGLF extends OBInstruction { + Opcode; + value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } + } + export class RAND extends OBInstruction { + Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } + } + export class F2I extends OBInstruction { + intRegIdx; + floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } + } + export class FSMSendMsgWait_Data extends OBInstruction { + TitleIdx; + TargetIdx; + BodyTypeID; + BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + } + export class FSMSendMsgWait extends OBInstruction { + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } + } + export class FSMBroadcastMsgWait extends OBInstruction { + TitleIdx; + BodyTypeID; + BodyRegisterIdx; + waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + export class TextJoin extends OBInstruction { + Left; + Right; + RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } + } + export class ToString extends OBInstruction { + ValueType; + ValueRegIdx; + RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + export class Sender extends OBInstruction { + RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } + } + export class SHL extends OBInstruction { + value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } + } + export class AND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } + } + export class FIX extends OBInstruction { + regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } + } + /** + * value of may by key + */ + export class VOM extends OBInstruction { + map; + key; + ValueType; + RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + export class LAND extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } + } + export class LOR extends OBInstruction { + a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 1 : 0; + } + }; + } + } + export class LNOT extends OBInstruction { + a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } + } + export class COND extends OBInstruction { + if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } + } + export class NEW extends OBInstruction { + StructDef; + Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFF0000) >> 16; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } + } + \ No newline at end of file -- Gitee From a2e0c0ac145e5bef0f3a2e4152826ab8a4340980 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Thu, 10 Mar 2022 02:38:28 +0800 Subject: [PATCH 20/30] =?UTF-8?q?IDE=20=E7=AD=BE=E5=90=8D=E6=88=90?= =?UTF-8?q?=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hap/build.gradle | 11 +++++++++++ hap/entry/build.gradle | 3 +++ .../src/main/js/MainAbility/common/canvas.js | 9 ++++++++- .../main/js/MainAbility/common/runtime/vm.js | 14 ++++++++++---- .../main/js/MainAbility/pages/index/index.js | 18 ++++++++++++++++-- 5 files changed, 48 insertions(+), 7 deletions(-) diff --git a/hap/build.gradle b/hap/build.gradle index f1b1a55..221dff7 100644 --- a/hap/build.gradle +++ b/hap/build.gradle @@ -3,6 +3,17 @@ apply plugin: 'com.huawei.ohos.app' //For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 ohos { + signingConfigs { + debug { + storeFile file('C:\\openharmony\\openharmonySign\\openharmonySign\\myApplication.p12') + storePassword '000000193E18D5D81837A2F38DFAA6366FFF7424CAC5A63EF3CA864D5F65018973039DE62DC15317A9' + keyAlias = 'hapsign' + keyPassword '00000019C9674C1BBC6BB5A041FAFF947C2315345DDE14EADC9E971C2A76CDF4C12CCE0DD625B9F6F5' + signAlg = 'SHA256withECDSA' + profile file('C:\\openharmony\\openharmonySign\\openharmonySign\\SgnedReleasedProfileTemplate.p7b') + certpath file('C:\\openharmony\\openharmonySign\\openharmonySign\\IDE.cer') + } + } compileSdkVersion 8 supportSystem "standard" } diff --git a/hap/entry/build.gradle b/hap/entry/build.gradle index 92a548d..4f27528 100644 --- a/hap/entry/build.gradle +++ b/hap/entry/build.gradle @@ -1,6 +1,9 @@ apply plugin: 'com.huawei.ohos.hap' //For instructions on signature configuration, see https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ide_debug_device-0000001053822404#section1112183053510 ohos { + signingConfigs { + } + // signingConfigs { // debug { // storeFile file('C:\\openharmony\\key1\\openharmony.p12') diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index e71acf5..1b1cfbc 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -29,6 +29,10 @@ export class OBCanvas2D { this.canvas = canvas; this.canvas2dctx = canvas.getContext('2d'); } + /** + * + * @param {Number} color + */ setFillStyleColor(color) { let str_color; if (color < 0) { @@ -39,8 +43,11 @@ export class OBCanvas2D { } this.canvas2dctx.fillStyle = str_color.substr(0, 7); } + /** + * + * @param {Number} color + */ setStrokeStyleColor(color) { - throw 'setStrokeStyleColor'; let str_color; if (color < 0) { str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 3f36218..b13fcd3 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -59,9 +59,10 @@ export class NativeUtil { builder.PushAction((st, f, local, pos) => { let argVals = argGetters.map(g => g(st, f, local)); try { + st.fsm.VM.Log('call: '); func.apply(null,argVals); }catch(e){ - st.fsm.VM.Log('Error: '+e+" "+func.name); + st.fsm.VM.Log('Error: '); } return pos + 1; }); @@ -95,7 +96,12 @@ export class NativeUtil { }); builder[retRegisterType][retRegIdx] = ((st, f, local) => { let argVals = argGetters.map(g => g(st, f, local)); - return func.apply(null, argVals); + try { + st.fsm.VM.Log('call: '); + return func.apply(null, argVals); + }catch(e){ + st.fsm.VM.Log('error: '); + } }); }; return f; @@ -2102,7 +2108,7 @@ export class OBEventMessage extends OBMessage { state.HandleEvent(this); } catch (err) { if (!(err instanceof VMInterruptException)) { - console.error(err); + state.fsm.VM.Log(err+""); throw err; } } @@ -2119,7 +2125,7 @@ export class OBUserMessage extends OBMessage { state.HandleMessage(this); } catch (err) { if (!(err instanceof VMInterruptException)) { - console.error(err); + state.fsm.VM.Log(err + ""); throw err; } } diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index 91087e4..f52537b 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -38,6 +38,18 @@ if (!String.prototype.padStart) { } }; } +if (!Object.values) Object.values = function(obj) { + if (obj !== Object(obj)) + throw new TypeError('Object.values called on a non-object'); + var val=[],key; + for (key in obj) { + if (Object.prototype.hasOwnProperty.call(obj,key)) { + val.push(obj[key]); + } + } + return val; +} + export default { @@ -145,13 +157,15 @@ export default { clearInterval(this.fileCheckInterval); }, update() { - if(this.info.length > 50){ - return; + if(this.info.length > 500){ + this.info = this.info.substring(500); } try { + this.log('update1'); if (this.vm) { this.vm.update(); } + this.log('update2'); }catch(e){ this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); } -- Gitee From 60e8f6aad316f33891e5322064fb729a3c6d8d43 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sat, 12 Mar 2022 12:46:36 +0800 Subject: [PATCH 21/30] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hap/entry/build.gradle | 1 + hap/entry/src/main/config.json | 5 ++ .../src/main/js/MainAbility/common/canvas.js | 51 ++++++----- .../main/js/MainAbility/common/runtime/vm.js | 90 ++++++++++++++----- .../main/js/MainAbility/pages/index/index.js | 9 +- .../js/MainAbility/pages/second/second.js | 36 ++------ 6 files changed, 119 insertions(+), 73 deletions(-) diff --git a/hap/entry/build.gradle b/hap/entry/build.gradle index 4f27528..527e37a 100644 --- a/hap/entry/build.gradle +++ b/hap/entry/build.gradle @@ -19,6 +19,7 @@ ohos { defaultConfig { compatibleSdkVersion 8 } +// arkEnable false buildTypes { release { proguardOpt { diff --git a/hap/entry/src/main/config.json b/hap/entry/src/main/config.json index 787cc5f..e1bf7af 100644 --- a/hap/entry/src/main/config.json +++ b/hap/entry/src/main/config.json @@ -9,6 +9,11 @@ }, "deviceConfig": {}, "module": { + "reqPermissions": [ + { + "name": "ohos.permission.WRITE_MEDIA" + } + ], "package": "com.openblock.ohos", "name": ".MyApplication", "mainAbility": ".MainAbility", diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index 1b1cfbc..4fdbc77 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -57,42 +57,51 @@ export class OBCanvas2D { } this.canvas2dctx.strokeStyle = str_color.substr(0, 7); } + getWidth(){ + return 750; + } + getHeight(){ + return 1280; + } /** * 安装到脚本库 * @param {OBScript} script */ install(script) { + this.canvas2dctx.fillRect(50,50,50,50); script.InstallLib("canvas2d", "canvas2d", [ - script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'fillRect'), + script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'clearRect'), // canvas2dctx.fillStyle=color - script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), - script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), - script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister'],'setFillStyleColor'), + script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'strokeRect'), + script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister'],'fillText'), + script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), [],'beginPath'), + script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'arc'), + script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), [],'fill'), + script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), [],'closePath'), script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'arcTo'), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'bezierCurveTo'), + script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister'],'moveTo'), + script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister'],'lineTo'), script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister'],'ellipse'), + script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'rect'), + script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister'],'rotate'), + script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister'],'scale'), + script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister'],'setStrokeStyleColor'), + script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), [],'stroke'), script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), +// script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), +// script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), + script.NativeUtil.closureReturnValue(this.getHeight.bind(this), 'LongRegister',[],'getHeight'), + script.NativeUtil.closureReturnValue(this.getWidth.bind(this), 'LongRegister',[],'getWidth'), script.NativeUtil.fieldSetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), ]); diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index b13fcd3..942b999 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -35,9 +35,10 @@ export class NativeUtil { * * @param {Function} func * @param {Number[]} argtype + * @param {String} funcname * @returns */ - static closureVoid(func, argtype) { + static closureVoid(func, argtype,funcname) { /** * * @param {OBFunctionBuilder} builder @@ -59,7 +60,8 @@ export class NativeUtil { builder.PushAction((st, f, local, pos) => { let argVals = argGetters.map(g => g(st, f, local)); try { - st.fsm.VM.Log('call: '); + let funcname1 = funcname; + st.fsm.VM.Log('call: '+funcname1); func.apply(null,argVals); }catch(e){ st.fsm.VM.Log('Error: '); @@ -72,10 +74,12 @@ export class NativeUtil { /** * * @param {Function} func + * @param {String} retRegisterType * @param {Number[]} argtype + * @param {String} funcname * @returns */ - static closureReturnValue(func, retRegisterType, argtype) { + static closureReturnValue(func, retRegisterType, argtype,funcname) { /** * * @param {OBFunctionBuilder} builder @@ -97,7 +101,8 @@ export class NativeUtil { builder[retRegisterType][retRegIdx] = ((st, f, local) => { let argVals = argGetters.map(g => g(st, f, local)); try { - st.fsm.VM.Log('call: '); + let funcname1 = funcname; + st.fsm.VM.Log('call: '+funcname1); return func.apply(null, argVals); }catch(e){ st.fsm.VM.Log('error: '); @@ -576,17 +581,17 @@ export class OBBuildInFunctions { OBBuildInFunctions.FSM_FindFsmByNameInstaller, OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister'],'Text_Length'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister'],'Text_IsEmpty'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister'],'Text_IndexOf'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister'],'Text_CharAt'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister'],'Text_GetSubstring'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister'],'Text_ToUpperCase'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister'],'Text_ToLowerCase'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister'],'Text_ToTitleCase'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister'],'Text_Count'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister'],'Text_Replace'), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister'],'Text_Reverse'), ]); } /** @@ -783,9 +788,14 @@ export class StructData { * @returns {OBStructValue} */ Get(type, id, loading) { + console.log('openblock StructData.Get 1 '+type+" "+id); + console.log('openblock StructData.Get 1 '+type.startsWith.name); + console.log('openblock StructData.Get 1 '+type.endsWith.name); if (type.startsWith("S") && type.endsWith(";")) { + console.log('openblock StructData.Get 1 '+type.substr.name); type = type.substr(1, type.length - 2); } + console.log('openblock StructData.Get 1.1 '+type+" "+id); if (loading == null) { loading = {}; } else { @@ -794,6 +804,7 @@ export class StructData { return loaded; } } + console.log('openblock StructData.Get 1.2 '+type+" "+id); let def = this.StructDef[type]; let group = this.Groups[type]; if(!group){ @@ -801,11 +812,13 @@ export class StructData { } let reader = group.Data; let itemStart = 0; + console.log('openblock StructData.Get 2 '+type+" "+id); for (let i = 0; i < group.StructCount; i++) { reader.pos = itemStart; let length = reader.ReadInt32(); let itemid = reader.ReadUInt32(); if (itemid === id) { + console.log('openblock StructData.Get 3 '+type+" "+id); reader.pos -= 4; let s = new OBStructValue(def); loading[id + "@" + type] = s; @@ -846,6 +859,7 @@ export class StructData { } else { itemStart += length * 4 + 4; } + console.log('openblock StructData.Get 4 '+type+" "+id); } throw Error("找不到 ID为" + id + "的" + type); } @@ -1062,6 +1076,7 @@ export class OBScriptLoader { let fsm = this.readFSM(reader); fsm.ModuleName = moduleName; fsm.FullName = moduleName + "." + fsm.Name; + console.log('openblock fsm:'+fsm.FullName); reader.pos = pos; f[i] = fsm; } @@ -1406,6 +1421,9 @@ export class OBArrayBufferReader { if (str === null) { throw Error('no string value of idx:' + stringIdx); } + console.log('openblock getString '+str); +// str = JSON.parse(JSON.stringify(str)); +// console.log('openblock getString after JSON '+str); this.stringCache[stringIdx] = str; return str; } @@ -1522,6 +1540,10 @@ export class OBVM { } let fsmdata = this.script.FullNameFSMData[name]; if (!fsmdata) { + for(let key in this.script.FullNameFSMData){ + console.log('openblock fsmlist:'+key +" length:"+key.length); + } + console.log('openblock notfound:'+name +" length:"+name.length); return null; } let uBFSM = new OBVMFSM(this, fsmdata); @@ -1546,6 +1568,7 @@ export class OBVM { while (this.Pending.length > 0) { let fsm = this.Pending.shift(); if (fsm) { + let fsmname = fsm.data.Name; fsm.HandleAllMessages(); } } @@ -1807,7 +1830,8 @@ export class OBVMState { */ HandleEvent(msg) { try { - let h = this.data.EventHandlers[msg.name]; + let msgname = msg.name; + let h = this.data.EventHandlers[msgname]; if (h) { this.currentMessage = msg; let vmf = new OBVMFunction(h.Func); @@ -1825,11 +1849,35 @@ export class OBVMState { if (m.arg != null) { typeName = m.GetArgType(); } - let hl = this.data.MessageHandlers[m.name]; + let mname = m.name; + let hl = this.data.MessageHandlers[mname]; + let self = this; if (hl) { hl.forEach(h => { - if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { - new OBVMFunction(h.Func).Call(this); +// let str_h = JSON.stringify(h); +// let hArgTypeName = JSON.parse( JSON.stringify( h.ArgTypeName)); + let hArgTypeName = h.ArgTypeName; +// let typeName1 = typeName; +// let b = hArgTypeName === typeName1; +// let b1 = hArgTypeName == typeName1; +// let l = hArgTypeName.length; +// let l1 = typeName1.length; +// let b2 = "Integer"==="Integer"; +// let b3 = hArgTypeName=="Integer"; +// let b4 = typeName1=="Integer"; +// +// let t = typeof(hArgTypeName); +// let t1 = typeof(typeName); +// let s1 = "Integer"; +// let s2 = "Integer"; +// let b5 = s1==s2; +// let b6 = s1===s2; + if (hArgTypeName === "" || hArgTypeName===typeName) { + let fd = h.Func; + let obvmf = new OBVMFunction(fd); + this.fsm.VM.Log("typeof obvmf.Call:"+typeof(obvmf.Call)); + this.fsm.VM.Log("method name:"+mname); + obvmf.Call(self); } }); } @@ -1941,6 +1989,8 @@ export class OBVMFunction { /** * * @param {OBVMState} state + * @param {OBVMFunction} uBFunction + * @param {Object} localVars */ Call(state, uBFunction, localVars) { if (uBFunction) { @@ -2125,7 +2175,7 @@ export class OBUserMessage extends OBMessage { state.HandleMessage(this); } catch (err) { if (!(err instanceof VMInterruptException)) { - state.fsm.VM.Log(err + ""); + state.fsm.VM.Log("Error:"+err); throw err; } } diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index f52537b..bf94df1 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -66,6 +66,7 @@ export default { }] }, log(s) { + console.log('OpenBlock '+s); this.info +="\n"+ s; }, ob_event(name) { @@ -101,7 +102,9 @@ export default { initStage() { let stage = this.$refs.canvas1; try { - filepath = "/data/"+app.getInfo().appID+"/main.xe"; + console.log('openblock 中文'+'测试'); + // /storage/media/100/local/files + filepath = "/data/storage/el1/base/main.xe";//"/data/"+app.getInfo().appID+"/main.xe"; this.log(filepath); stage.width = stage.width; let fd = fileio.openSync(filepath, 0o2); @@ -137,7 +140,7 @@ export default { this.uninited = false; this.initStage(); } - this.updateInterval = setInterval(this.update, 30); + this.updateInterval = setInterval(this.update, 3000); this.fileCheckInterval = setInterval(this.checkFile, 3000); },1); }, @@ -161,11 +164,9 @@ export default { this.info = this.info.substring(500); } try { - this.log('update1'); if (this.vm) { this.vm.update(); } - this.log('update2'); }catch(e){ this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); } diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.js b/hap/entry/src/main/js/MainAbility/pages/second/second.js index 32b3abd..f1a95dc 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/second.js +++ b/hap/entry/src/main/js/MainAbility/pages/second/second.js @@ -1,5 +1,4 @@ import router from '@system.router' -import fetch from '@system.fetch'; export default { data: { @@ -10,33 +9,14 @@ export default { }, onclick: function () { this.log('0'); - try{ - fetch.fetch({ - url: 'http://122.9.129.166:1918/login/', - method: "POST", - data: { - uid: '123', - pwd: '123', - }}); - }catch(e){ - this.log("\n fetch ERROR:"+e.toString()+"\n" + JSON.stringify(e)); - return; - } - try { - this.log('1'); - function f(v,w){ - this.log(v); - this.log(w); - } - let tf = [f.bind(this)]; + let str = String(JSON.parse(JSON.stringify("中文"))); + let b = str == "中文"; + this.log(b); // 这里是false setTimeout(()=>{ - tf[0].apply(null,['4','5']); - },100); - tf[0].apply(null,['2','3']); - } catch (e) { - this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); - } finally { - this.log('h'); - } + this.log(str); //这里会导致整个字符串消失,应该是乱码了 + },2000); + setTimeout(()=>{ + this.log(str.startsWith('中')); //这里会导致整程序崩溃 + },4000); } } -- Gitee From 6892d644137e6e20c845bd93e3b53e45d7eb2c5e Mon Sep 17 00:00:00 2001 From: duzc2 Date: Mon, 14 Mar 2022 03:40:01 +0800 Subject: [PATCH 22/30] 1 --- .../pages/second/{second.css => page.css} | 0 .../pages/second/{second.hml => page.hml} | 0 .../main/js/MainAbility/pages/second/page.js | 64 +++++++++++++++++++ .../js/MainAbility/pages/second/second.js | 22 ------- .../js/MainAbility/pages/third/second.css | 20 ++++++ .../js/MainAbility/pages/third/second.hml | 6 ++ .../main/js/MainAbility/pages/third/second.js | 64 +++++++++++++++++++ 7 files changed, 154 insertions(+), 22 deletions(-) rename hap/entry/src/main/js/MainAbility/pages/second/{second.css => page.css} (100%) rename hap/entry/src/main/js/MainAbility/pages/second/{second.hml => page.hml} (100%) create mode 100644 hap/entry/src/main/js/MainAbility/pages/second/page.js delete mode 100644 hap/entry/src/main/js/MainAbility/pages/second/second.js create mode 100644 hap/entry/src/main/js/MainAbility/pages/third/second.css create mode 100644 hap/entry/src/main/js/MainAbility/pages/third/second.hml create mode 100644 hap/entry/src/main/js/MainAbility/pages/third/second.js diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.css b/hap/entry/src/main/js/MainAbility/pages/second/page.css similarity index 100% rename from hap/entry/src/main/js/MainAbility/pages/second/second.css rename to hap/entry/src/main/js/MainAbility/pages/second/page.css diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.hml b/hap/entry/src/main/js/MainAbility/pages/second/page.hml similarity index 100% rename from hap/entry/src/main/js/MainAbility/pages/second/second.hml rename to hap/entry/src/main/js/MainAbility/pages/second/page.hml diff --git a/hap/entry/src/main/js/MainAbility/pages/second/page.js b/hap/entry/src/main/js/MainAbility/pages/second/page.js new file mode 100644 index 0000000..93a75dd --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/second/page.js @@ -0,0 +1,64 @@ +import router from '@system.router' + +import util from '@ohos.util' +export default { + data: { + info: 'World' + }, + log(s) { + this.info += "\n" + s; + }, + onclick: function () { + let code = [83 +, 116 +, 97 +, 114 +, 116 +, 46 +, 229 +, 155 +, 189 +, 229 +, 174 +, 182 +, 231 +, 130 +, 185] + + let ui8 = new Uint8Array(code); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + let str = utf8decoder.decode(ui8); + console.log('openblock getString '+str); + let cache = {}; + cache[4] = str; + setTimeout(()=>{ + + let ostr = cache[4]; + console.log('openblock String '+ostr); + console.log('openblock comp String '+(str==ostr)); + let obj = {}; + obj[str] = "abc"; + + setTimeout(()=>{ + let value = obj[ostr]; + console.log('openblock value:'+value); + obj[ostr] = "bcd"; + value = obj[str]; + console.log('openblock value:'+value); + value = obj[ostr]; + console.log('openblock value:'+value); + + let value1 = JSON.parse(JSON.stringify(value)); + console.log('openblock value1:'+value1); + console.log('openblock comp value01:'+(value==value1)); + + value = 'Start.国家点'; + value1 = cache[4]; + console.log('openblock value1:'+value1); + console.log('openblock comp value01:'+(value==value1)); + },5); + },5); + } +} diff --git a/hap/entry/src/main/js/MainAbility/pages/second/second.js b/hap/entry/src/main/js/MainAbility/pages/second/second.js deleted file mode 100644 index f1a95dc..0000000 --- a/hap/entry/src/main/js/MainAbility/pages/second/second.js +++ /dev/null @@ -1,22 +0,0 @@ -import router from '@system.router' - -export default { - data: { - info: 'World' - }, - log(s) { - this.info +="\n"+ s; - }, - onclick: function () { - this.log('0'); - let str = String(JSON.parse(JSON.stringify("中文"))); - let b = str == "中文"; - this.log(b); // 这里是false - setTimeout(()=>{ - this.log(str); //这里会导致整个字符串消失,应该是乱码了 - },2000); - setTimeout(()=>{ - this.log(str.startsWith('中')); //这里会导致整程序崩溃 - },4000); - } -} diff --git a/hap/entry/src/main/js/MainAbility/pages/third/second.css b/hap/entry/src/main/js/MainAbility/pages/third/second.css new file mode 100644 index 0000000..5a91124 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/third/second.css @@ -0,0 +1,20 @@ +.container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + left: 0px; + top: 0px; + width: 100%; + height: 100%; +} + +.title { + font-size: 30px; +} + +.btn { + width: 50%; + height: 100px; + font-size: 40px; +} diff --git a/hap/entry/src/main/js/MainAbility/pages/third/second.hml b/hap/entry/src/main/js/MainAbility/pages/third/second.hml new file mode 100644 index 0000000..0a0d321 --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/third/second.hml @@ -0,0 +1,6 @@ +
+ + + {{info}} + +
diff --git a/hap/entry/src/main/js/MainAbility/pages/third/second.js b/hap/entry/src/main/js/MainAbility/pages/third/second.js new file mode 100644 index 0000000..93a75dd --- /dev/null +++ b/hap/entry/src/main/js/MainAbility/pages/third/second.js @@ -0,0 +1,64 @@ +import router from '@system.router' + +import util from '@ohos.util' +export default { + data: { + info: 'World' + }, + log(s) { + this.info += "\n" + s; + }, + onclick: function () { + let code = [83 +, 116 +, 97 +, 114 +, 116 +, 46 +, 229 +, 155 +, 189 +, 229 +, 174 +, 182 +, 231 +, 130 +, 185] + + let ui8 = new Uint8Array(code); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + let str = utf8decoder.decode(ui8); + console.log('openblock getString '+str); + let cache = {}; + cache[4] = str; + setTimeout(()=>{ + + let ostr = cache[4]; + console.log('openblock String '+ostr); + console.log('openblock comp String '+(str==ostr)); + let obj = {}; + obj[str] = "abc"; + + setTimeout(()=>{ + let value = obj[ostr]; + console.log('openblock value:'+value); + obj[ostr] = "bcd"; + value = obj[str]; + console.log('openblock value:'+value); + value = obj[ostr]; + console.log('openblock value:'+value); + + let value1 = JSON.parse(JSON.stringify(value)); + console.log('openblock value1:'+value1); + console.log('openblock comp value01:'+(value==value1)); + + value = 'Start.国家点'; + value1 = cache[4]; + console.log('openblock value1:'+value1); + console.log('openblock comp value01:'+(value==value1)); + },5); + },5); + } +} -- Gitee From d7ca1f7343c96f5782ce5261c13439bca00a78a0 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Mon, 14 Mar 2022 03:40:11 +0800 Subject: [PATCH 23/30] 1 --- .../main/js/MainAbility/common/runtime/vm.js | 21 ++++++-- .../main/js/MainAbility/pages/index/index.js | 1 + .../main/js/MainAbility/pages/second/page.js | 51 ------------------- 3 files changed, 19 insertions(+), 54 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 942b999..987862d 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -1421,7 +1421,10 @@ export class OBArrayBufferReader { if (str === null) { throw Error('no string value of idx:' + stringIdx); } - console.log('openblock getString '+str); + console.log('openblock getString '+str + + ' byteLength ' + ab.byteLength + + ' index ' + stringIdx + + ' Length ' + str.length); // str = JSON.parse(JSON.stringify(str)); // console.log('openblock getString after JSON '+str); this.stringCache[stringIdx] = str; @@ -1538,12 +1541,24 @@ export class OBVM { if (this.script == null) { throw Error("Script is null"); } + console.log('openblock typeof data '+ typeof(this.script.FullNameFSMData)); + let testobj = {"abc": 123} + console.log("openblock "+testobj.abc) + console.log("openblock "+this.script.FullNameFSMData["xfan1"]); let fsmdata = this.script.FullNameFSMData[name]; if (!fsmdata) { + console.log('openblock fsmdata '+fsmdata); + console.log('openblock notfound:'+name +" length:"+name.length + " line 1546"); for(let key in this.script.FullNameFSMData){ - console.log('openblock fsmlist:'+key +" length:"+key.length); + console.log('openblock fsmlist:'+key +" length:"+key.length+ " line 1548"); + console.log('openblock fsmname compare :'+(key === name)+ " line 1549"); + if(key===name){ + fsmdata = this.script.FullNameFSMData[key]; + let c = name==='1234567890'; + console.log('openblock fsmdata1 '+fsmdata + ","+c); + return fsmdata; + } } - console.log('openblock notfound:'+name +" length:"+name.length); return null; } let uBFSM = new OBVMFSM(this, fsmdata); diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index bf94df1..e7833e4 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -101,6 +101,7 @@ export default { }, initStage() { let stage = this.$refs.canvas1; + try { console.log('openblock 中文'+'测试'); // /storage/media/100/local/files diff --git a/hap/entry/src/main/js/MainAbility/pages/second/page.js b/hap/entry/src/main/js/MainAbility/pages/second/page.js index 93a75dd..e77d8b6 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/page.js +++ b/hap/entry/src/main/js/MainAbility/pages/second/page.js @@ -9,56 +9,5 @@ export default { this.info += "\n" + s; }, onclick: function () { - let code = [83 -, 116 -, 97 -, 114 -, 116 -, 46 -, 229 -, 155 -, 189 -, 229 -, 174 -, 182 -, 231 -, 130 -, 185] - - let ui8 = new Uint8Array(code); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - let str = utf8decoder.decode(ui8); - console.log('openblock getString '+str); - let cache = {}; - cache[4] = str; - setTimeout(()=>{ - - let ostr = cache[4]; - console.log('openblock String '+ostr); - console.log('openblock comp String '+(str==ostr)); - let obj = {}; - obj[str] = "abc"; - - setTimeout(()=>{ - let value = obj[ostr]; - console.log('openblock value:'+value); - obj[ostr] = "bcd"; - value = obj[str]; - console.log('openblock value:'+value); - value = obj[ostr]; - console.log('openblock value:'+value); - - let value1 = JSON.parse(JSON.stringify(value)); - console.log('openblock value1:'+value1); - console.log('openblock comp value01:'+(value==value1)); - - value = 'Start.国家点'; - value1 = cache[4]; - console.log('openblock value1:'+value1); - console.log('openblock comp value01:'+(value==value1)); - },5); - },5); } } -- Gitee From 8f1720ba689e9a9557ab51b21e591dbfb013d628 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sat, 9 Apr 2022 23:25:27 +0800 Subject: [PATCH 24/30] =?UTF-8?q?3.1=20release=20=E5=B7=A5=E7=A8=8B?= =?UTF-8?q?=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hap/.gitignore | 18 +- hap/build-profile.json5 | 40 + hap/entry/.gitignore | 3 +- hap/entry/build-profile.json5 | 10 + hap/entry/hvigorfile.js | 2 + hap/entry/package-lock.json | 5 + hap/entry/package.json | 15 +- hap/entry/src/main/config.json | 10 +- .../main/js/MainAbility/common/runtime/vm.js | 8887 +++++++++-------- .../src/main/js/MainAbility/i18n/en-US.json | 5 +- .../src/main/js/MainAbility/i18n/zh-CN.json | 5 +- .../main/js/MainAbility/pages/second/page.js | 9 + .../main/resources/base/element/string.json | 12 +- hap/hvigorfile.js | 2 + hap/local.properties | 15 +- hap/package-lock.json | 1643 +++ hap/package.json | 19 +- 17 files changed, 6240 insertions(+), 4460 deletions(-) create mode 100644 hap/build-profile.json5 create mode 100644 hap/entry/build-profile.json5 create mode 100644 hap/entry/hvigorfile.js create mode 100644 hap/entry/package-lock.json create mode 100644 hap/hvigorfile.js create mode 100644 hap/package-lock.json diff --git a/hap/.gitignore b/hap/.gitignore index fdc0c4a..39187eb 100644 --- a/hap/.gitignore +++ b/hap/.gitignore @@ -1,16 +1,4 @@ -*.iml -.gradle -/local.properties -/.idea/caches -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml -/.idea/navEditor.xml -/.idea/assetWizardSettings.xml -.DS_Store -/build -/captures -.externalNativeBuild -/entry/.preview -.cxx /node_modules +/local.properties +/.idea +**/build \ No newline at end of file diff --git a/hap/build-profile.json5 b/hap/build-profile.json5 new file mode 100644 index 0000000..413dbce --- /dev/null +++ b/hap/build-profile.json5 @@ -0,0 +1,40 @@ +{ + "app": { + "signingConfigs": [ + { + "name": "default", + "material": { + "certpath": "C:\\Users\\Administrator\\.ohos\\config\\openharmony\\auto_ohos.cer", + "storePassword": "00000018D4659CE60A452595A5380056CEC64ABD02FF8B645D2A2414105DE14B89A046AD753F1599", + "keyAlias": "debugKey", + "keyPassword": "00000018F2E89E372997C86EA77B3D5E94E47AEBF65CA6FBD2880B64E3790763423E5689CFE1D8C3", + "profile": "C:\\Users\\Administrator\\.ohos\\config\\openharmony\\auto_ohos_default_com.openblock.ohos.p7b", + "signAlg": "SHA256withECDSA", + "storeFile": "C:\\Users\\Administrator\\.ohos\\config\\openharmony\\auto_ohos.p12" + } + } + ], + "compileSdkVersion": 8, + "compatibleSdkVersion": 8, + "products": [ + { + "name": "default", + "signingConfig": "default", + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/hap/entry/.gitignore b/hap/entry/.gitignore index 7d5b7a9..4f9a973 100644 --- a/hap/entry/.gitignore +++ b/hap/entry/.gitignore @@ -1,2 +1,3 @@ -/build /node_modules +/.preview +/build \ No newline at end of file diff --git a/hap/entry/build-profile.json5 b/hap/entry/build-profile.json5 new file mode 100644 index 0000000..09fbaf4 --- /dev/null +++ b/hap/entry/build-profile.json5 @@ -0,0 +1,10 @@ +{ + "apiType": 'faMode', + "buildOption": { + }, + "targets": [ + { + "name": "default", + } + ] +} \ No newline at end of file diff --git a/hap/entry/hvigorfile.js b/hap/entry/hvigorfile.js new file mode 100644 index 0000000..bcec4c9 --- /dev/null +++ b/hap/entry/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyHapTasks diff --git a/hap/entry/package-lock.json b/hap/entry/package-lock.json new file mode 100644 index 0000000..15bc714 --- /dev/null +++ b/hap/entry/package-lock.json @@ -0,0 +1,5 @@ +{ + "name": "entry", + "version": "1.0.0", + "lockfileVersion": 1 +} diff --git a/hap/entry/package.json b/hap/entry/package.json index 0967ef4..c7685ac 100644 --- a/hap/entry/package.json +++ b/hap/entry/package.json @@ -1 +1,14 @@ -{} +{ + "license": "ISC", + "devDependencies": {}, + "name": "entry", + "ohos": { + "org": "huawei", + "directoryLevel": "module", + "buildTool": "hvigor" + }, + "description": "example description", + "repository": {}, + "version": "1.0.0", + "dependencies": {} +} diff --git a/hap/entry/src/main/config.json b/hap/entry/src/main/config.json index e1bf7af..f09c9bf 100644 --- a/hap/entry/src/main/config.json +++ b/hap/entry/src/main/config.json @@ -15,10 +15,11 @@ } ], "package": "com.openblock.ohos", - "name": ".MyApplication", + "name": ".entry", "mainAbility": ".MainAbility", "deviceType": [ - "phone" + "phone", + "tablet" ], "distro": { "deliveryWithInstall": true, @@ -26,6 +27,7 @@ "moduleType": "entry", "installationFree": false }, + "srcPath": "", "abilities": [ { "skills": [ @@ -44,9 +46,9 @@ "name": ".MainAbility", "srcLanguage": "js", "icon": "$media:icon", - "description": "$string:description_mainability", + "description": "$string:MainAbility_desc", "formsEnabled": false, - "label": "$string:entry_MainAbility", + "label": "$string:MainAbility_label", "type": "page", "launchType": "standard" } diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 987862d..a767285 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -3,4420 +3,4473 @@ * Copyright 2021 Du Tian Wei * SPDX-License-Identifier: Apache-2.0 */ -import * as util from './util.js' -export class NativeUtil { - - static fieldSetter(target, fieldName, register) { - return (builder, args) => { - let getter = builder[register][args[1] & 0xfff]; - builder.PushAction((st, f, local, pos) => { - let v = getter(st, f, local); - target[fieldName] = v; - return 1 + pos; - }); - }; - } - static fieldGetter(target, fieldName, register) { - return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { - return target[fieldName]; - }; - }; - } - static objFieldGetter(fieldName, fieldRegister) { - return (builder, args) => { - let obj = builder.NObjectRegister[args[1] & 0xfff]; - builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { - return obj(st, f, local)[fieldName]; - }; - }; - } - /** - * - * @param {Function} func - * @param {Number[]} argtype - * @param {String} funcname - * @returns - */ - static closureVoid(func, argtype,funcname) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - if (typeof (v) != 'function') { - debugger - } - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder.PushAction((st, f, local, pos) => { - let argVals = argGetters.map(g => g(st, f, local)); - try { - let funcname1 = funcname; - st.fsm.VM.Log('call: '+funcname1); - func.apply(null,argVals); - }catch(e){ - st.fsm.VM.Log('Error: '); - } - return pos + 1; - }); - }; - return f; - } - /** - * - * @param {Function} func - * @param {String} retRegisterType - * @param {Number[]} argtype - * @param {String} funcname - * @returns - */ - static closureReturnValue(func, retRegisterType, argtype,funcname) { - /** - * - * @param {OBFunctionBuilder} builder - * @param {Number[]} args - * @returns - */ - let f = (builder, args) => { - let retRegIdx = args[0]; - let retType = (retRegIdx & 0xF000) >> 12; - retRegIdx = retRegIdx & 0xFFF; - args = args.slice(1); - let argGetters = argtype.map((rtype, idx) => { - let idx1 = args[idx] & 0xFFF; - let v = builder[rtype][idx1]; - return (st, f, local) => { - return v(st, f, local); - }; - }); - builder[retRegisterType][retRegIdx] = ((st, f, local) => { - let argVals = argGetters.map(g => g(st, f, local)); - try { - let funcname1 = funcname; - st.fsm.VM.Log('call: '+funcname1); - return func.apply(null, argVals); - }catch(e){ - st.fsm.VM.Log('error: '); - } - }); - }; - return f; - } -} -export class OBScript { - NativeLibHash = {}; // libname->hash - InstalledLibs = {}; - NativeUtil = NativeUtil; - /** - * @1type {StructData} - */ - StructData = {}; //typename->OBStructValueData - /** - * @type {Object.} - */ - StructDef = {}; // typename-> def - loadedFunctions; //= {};//function sign->function - FullNameFSMData = {}; //FullName->OBFSM - - /** - * @callback FuncInstaller - * @param {OBFunctionBuilder} funcBuilder - * @param {number[]} registersConfig - */ - /** - * 安装本地库 - * @param {string} libName - * @param {string} jsmd5 md5 of js generated config - * @param {FuncInstaller[]} funcInstallers array of funcInstaller - */ - InstallLib(libName, jsmd5, funcInstallers) { - if (this.InstalledLibs[libName]) { - throw Error("重复导入 " + libName); - } - this.InstalledLibs[libName] = funcInstallers; - this.NativeLibHash[libName] = jsmd5; - } - /** - * - * @param {string} libname - * @param {number} funcIdx - */ - getNativeFunc(libname, funcIdx) { - if (funcIdx < 0) { - throw Error("funcIdx:" + funcIdx); - } - // Action < UFunctionBuilder, int[] > [] lib; - let lib = this.InstalledLibs[libname]; - if (lib) { - if (funcIdx < lib.length) { - return lib[funcIdx]; - } else { - throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); - } - } else { - throw Error("Native lib " + libname + " not found"); - } - } -} -export class OBStructDef { - Name; //string - StructCnt; // int - StringCnt; // int - IntegerCnt; // int - FloatCnt; // int - NobjectCnt; // int - StructFields; // int -} -export class OBStructValueData { - /** - * @type {OBArrayBufferReader} - */ - Data; //arraybuffer - FullName; - Offset; - Length; - StructCount; -} -export class OBVariableInfo { - typeIdx; - count; - - constructor(typeIdx, count) { - this.typeIdx = typeIdx; - this.count = count; - } -} -export class OBState { - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - Name; - MessageHandlers; - EventHandlers; -} -export class OBCodeSegment { - name; - functions; - fsms; -} -export class OBFunction { - /** - * @type {OBVariableInfo[]} - */ - Variables; - instructions; - /** - * @type {String} - */ - Signure; - Statements; -} -export class OBFSM { - /** - * @type {string} - */ - Name; - /** - * @type {Object.} - */ - States; //string->state - /** - * @type {OBState} - */ - Entry; //state - /** - * @type {OBVariableInfo[]} - */ - Variables; - /** - * @type {string} - */ - FullName; - /** - * @type {string} - */ - ModuleName; -} -export class OBMessageHandler { - Name; - Func; - ArgTypeName; -} -export class OBEventHandler { - Name; - Func; -} -export class OBInstruction { - Position; - /** - * - * @param {number} code - * @param {OBFunctionBuilder} builder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - init(code, builder, instructions, i) { - - } - /** - * - * @param {OBFunctionBuilder} funcbuilder - * @param {OBInstruction[]} instructions - * @param {number} i - */ - link(funcbuilder, instructions, i) { - - } -} -export class OBByteCodes { - static createInstruction(cmd) { - switch (cmd) { - //case 0: - // break; - case 1: - return new PRT(); - case 2: - return new ARITHI(); - case 3: - return new ARITHF(); - case 4: - return new LDSTR(); - case 5: - return new LDI(); - case 6: - return new LDF(); - case 7: - return new RET(); - case 8: - throw Error("Unknown byte code command:" + cmd); - case 9: - throw Error("Unknown byte code command:" + cmd); - case 10: - return new CHSTT(); - case 11: - return new STVG(); - case 12: - return new FSMVS(); - case 13: - return new FSMVG(); - case 14: - return new STVS(); - case 15: - return new MethodCall(); - case 16: - return new MethodCallRegisterInfoAnchor(); - case 17: - return new CreateFSM(); - case 18: - return new FSMSendMsg(); - case 19: - return new ReceivedMessage(); - case 20: - return new GetStructField(); - case 21: - return new SetStructField(); - case 22: - return new GZ0(); - case 23: - return new BRIF(); - case 24: - return new DEC(); - case 25: - return new BR(); - case 26: - return new Reg2Var(); - case 27: - return new Var2Reg(); - case 28: - return new NOP(); - case 29: - return new BRIFN(); - case 30: - return new I2F(); - case 31: - return new StructFieldDesc(); - case 32: - return new EQ(); - case 33: - return new NEQ(); - case 34: - return new LT(); - case 35: - return new LTE(); - case 36: - return new GT(); - case 37: - return new GTE(); - case 38: - return new SLF(); - case 39: - return new NativeMethodCall(); - case 40: - return new DestroyFSM(); - case 41: - return new FSMBroadcastMsg(); - case 42: - return new SGLF(); - case 43: - return new RAND(); - case 44: - return new F2I(); - case 45: - return new FSMSendMsgWait_Data(); - case 46: - return new FSMSendMsgWait(); - case 47: - return new FSMBroadcastMsgWait(); - case 48: - return new TextJoin(); - case 49: - return new ToString(); - case 50: - return new Sender(); - case 51: - return new VOM(); - case 52: - return new SHL(); - case 53: - return new AND(); - case 54: - return new FIX(); - case 55: - return new LAND(); - case 56: - return new LOR(); - case 57: - return new LNOT(); - case 58: - return new COND(); - case 59: - return new NEW(); - default: - throw Error("Unknown byte code command:" + cmd); - } - // return new OBInstruction(cmd); - } -} -export class PositionUpdatePair { - targetOffset; - callback; -} -export class OBFunctionBuilder { - loader; //OBScriptLoader - StatementLength; //integer - BuildingFunc; //OBFunction - PositionUpdatePairList; - currentInstructPosition; //integer - RootStatementContext = new OBStatementContext(); //[StatementContext] - - /** - * @callback LongRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type LongRegister[] - */ - LongRegister; - /** - * @callback DoubleRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {number} - */ - /** - * @type DoubleRegister[] - */ - DoubleRegister; - /** - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {string} - */ - /** - * @type StringRegister[] - */ - StringRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {OBStructValue} - */ - /** - * @type {Array} StructRegister[] - */ - StructRegister; - /*@ - * @callback StringRegister - * @param {OBVMState} - * @param {OBFunctionBuilder} - * @param {OBInstruction[]} - * @returns {object} - */ - /** - * @type {Array} NObjectRegister[] - */ - NObjectRegister; - - constructor(loader) { - this.loader = loader; - } - - loadFunctionHeader(reader) { - let data = this.loader.data; - let BuildingFunc = new OBFunction(); - this.BuildingFunc = BuildingFunc; - - let header = reader.ReadUInt32(); - let pos = reader.pos; - // this.StatementLength = header * 4 - pos; - reader.pos = header * 4; - let nameIdx = reader.ReadUInt32(); - BuildingFunc.Signure = data.GetString(nameIdx); - this.LongRegister = []; - this.LongRegister.length = reader.ReadUInt32(); - this.DoubleRegister = []; - this.DoubleRegister.length = reader.ReadUInt32(); - this.StringRegister = []; - this.StringRegister.length = reader.ReadUInt32(); - this.StructRegister = []; - this.StructRegister.length = reader.ReadUInt32(); - this.NObjectRegister = []; - this.NObjectRegister.length = reader.ReadUInt32(); - let varInfo = []; - for (let i = 0; i < 5; i++) { - let info = new OBVariableInfo(); - info.typeIdx = i; - info.count = reader.ReadUInt32(); - varInfo[i] = info; - } - this.StatementLength = reader.ReadUInt32(); - BuildingFunc.Variables = varInfo; - reader.pos = pos; - } - - loadStatement(reader) { - let length = this.StatementLength; - this.BuildingFunc.instructions = []; - this.PositionUpdatePairList = []; //[PositionUpdatePair] - for (let i = 0; i < length; i++) { - let instPos = reader.pos; - let code = reader.ReadUInt32(); - let cmd = (code >> 24); - let inst = OBByteCodes.createInstruction(cmd); - inst.Position = instPos; - inst.init(code, this, this.BuildingFunc.instructions, i); - this.BuildingFunc.instructions[i] = inst; - } - } - - link() { - let instructions = this.BuildingFunc.instructions; - for (let i = 0; i < instructions.length; i++) { - let inst = instructions[i]; - this.currentInstructPosition = inst.Position; - inst.link(this, instructions, i); - } - this.PositionUpdatePairList = null; - this.BuildingFunc.Statements = this.RootStatementContext; - } - - build() { - return this.BuildingFunc; - } - - PositionUpdate(targetOffset, callback) { - if (this.PositionUpdatePairList == null) { - throw Error("异常状态"); - } - let p = new PositionUpdatePair(); - p.targetOffset = targetOffset; - p.callback = callback; - this.PositionUpdatePairList.push(p); - } - - PushAction(Instruction) { - if(!Instruction){ - throw 'Instruction is null,1'; - } - let stmt = this.RootStatementContext; - let newPos = stmt.Actions.length; - stmt.PushAction(Instruction); - this.PositionUpdatePairList.forEach((p) => { - if (p.targetOffset === this.currentInstructPosition) { - p.callback(newPos); - } - }); - } -} - -export class OBBuildInFunctions { - /** - * - * @param {OBScript} script - */ - static install(script) { - script.InstallLib("", "", [ - OBBuildInFunctions.FSM_FindFsmByTypeInstaller, - OBBuildInFunctions.FSM_FindFsmByNameInstaller, - OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, - // OBBuildInFunctions.FSM_TargetInstaller, - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister'],'Text_Length'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister'],'Text_IsEmpty'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister'],'Text_IndexOf'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister'],'Text_CharAt'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister'],'Text_GetSubstring'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister'],'Text_ToUpperCase'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister'],'Text_ToLowerCase'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister'],'Text_ToTitleCase'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister'],'Text_Count'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister'],'Text_Replace'), - script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister'],'Text_Reverse'), - ]); - } - /** - * - * @param {String} str - * @returns - */ - static Text_Reverse(str) { - if (str) { - return str.split('').reverse().join(''); - } else { - return ""; - } - } - static Text_Replace(haystack, needle, replacement) { - needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { - let t = start; - start = end; - end = t; - } - return str.substring(start, end + 1); - } - static Text_CharAt(str, index) { - if (index === 0) { - return ""; - } - if (index > 0) { - return str[index - 1] || ""; - } - if (index < 0) { - return str[str.length + index]; - } - } - static Text_IndexOf(str, sub, forward) { - if (forward === 1) { - return str.indexOf(sub) + 1; - } else { - return str.lastIndexOf(sub) + 1; - } - } - static Text_IsEmpty(str) { - return str.length === 0 ? 1 : 0; - } - static Text_Length(str) { - return str.length; - } - static FSM_FindFsmByTypeInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let argIdx = args[1] & 0xFFF; - let a1 = builder.StringRegister[argIdx]; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); - return r; - }; - } - static FSM_FindFsmByNameInstaller() { - } - static Structs_LoadStructFromDatasetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - let idIdx = args[2] & 0xFFF; - let a1 = builder.LongRegister[idIdx]; - let typeIdx = args[1] & 0xFFF; - let a2 = builder.StringRegister[typeIdx]; - let StructData = builder.loader.script.StructData; - builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { - let typename = a2(state, func, locals); - let id = a1(state, func, locals); - let r = StructData.Get(typename, id); - if(!r){ - throw `Can't find ${typename} which id is ${id}`; - } - return r; - }; - } - static FSM_TargetInstaller(builder, args) { - let returnRegisterIdx = args[0] & 0xFFF; - builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { - return state.fsm.Target; - }; - } -} -export class OBStructValue { - /** - * @type {OBStructDef} - */ - Def; - /** - * @type {OBTypedVariableGroup} - */ - registers; - - constructor(Def) { - this.Def = Def; - let registers = new OBTypedVariableGroup(null); - registers.LongRegister = []; - registers.LongRegister.fill(0, 0, Def.IntegerCnt); - registers.DoubleRegister = []; - registers.DoubleRegister.fill(0, 0, Def.FloatCnt); - registers.StringRegister = []; - registers.StringRegister.fill('', 0, Def.StringCnt); - registers.StructRegister = []; - registers.StructRegister.length = Def.StructCnt; - registers.NObjectRegister = []; - registers.NObjectRegister.length = Def.NobjectCnt; - this.registers = registers; - } - - toString() { - return "Struct." + this.Def.Name; - } -} -export class StructData { - /** - * @type {Object.} - */ - StructDef; - /** - * @type {Object.} - */ - Groups; - /** - * @type {OBArrayBufferReader} - */ - DataSegment; - - constructor(structDataGroups, data) { - this.Groups = structDataGroups; - this.DataSegment = data; - } - /** - * - * @param {string} type fullname of type - * @1param {integer} id id of data - * @param {?Object.} - * @returns {OBStructValue} - */ - Get(type, id, loading) { - console.log('openblock StructData.Get 1 '+type+" "+id); - console.log('openblock StructData.Get 1 '+type.startsWith.name); - console.log('openblock StructData.Get 1 '+type.endsWith.name); - if (type.startsWith("S") && type.endsWith(";")) { - console.log('openblock StructData.Get 1 '+type.substr.name); - type = type.substr(1, type.length - 2); - } - console.log('openblock StructData.Get 1.1 '+type+" "+id); - if (loading == null) { - loading = {}; - } else { - let loaded = loading[id + "@" + type]; - if (loaded) { - return loaded; - } - } - console.log('openblock StructData.Get 1.2 '+type+" "+id); - let def = this.StructDef[type]; - let group = this.Groups[type]; - if(!group){ - throw `There is no preset data of the type ${type}`; - } - let reader = group.Data; - let itemStart = 0; - console.log('openblock StructData.Get 2 '+type+" "+id); - for (let i = 0; i < group.StructCount; i++) { - reader.pos = itemStart; - let length = reader.ReadInt32(); - let itemid = reader.ReadUInt32(); - if (itemid === id) { - console.log('openblock StructData.Get 3 '+type+" "+id); - reader.pos -= 4; - let s = new OBStructValue(def); - loading[id + "@" + type] = s; - for (let j = 0; j < def.IntegerCnt; j++) { - s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); - } - for (let j = 0; j < def.StringCnt; j++) { - let idx = reader.ReadUInt32(); - let str = this.DataSegment.GetString(idx); - s.registers.StringRegister[j] = str; //VariableValueSet(j, str); - } - for (let j = 0; j < def.FloatCnt; j++) { - s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); - } - for (let j = 0; j < def.StructCnt; j++) { - let fieldDef = def.StructFields[j]; - if (fieldDef.startsWith("S")) { - let subId = reader.ReadUInt32(); - let subStruct = this.Get(def.StructFields[j], subId, loading); - s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); - } else if (fieldDef.startsWith("I")) { - // TODO - } else if (fieldDef.startsWith("N")) { - let elementTypeName = fieldDef.substr(1); - let structCnt = reader.ReadUInt32(); - let map = {}; - for (let k = 0; k < structCnt; k++) { - let keyIdx = reader.ReadUInt32(); - let keyStr = this.DataSegment.GetString(keyIdx); - let structId = reader.ReadInt32(); - let st = this.Get(elementTypeName, structId, loading); - map[keyStr] = st; - } - s.registers.StructRegister[j] = map; - } - } - return s; - } else { - itemStart += length * 4 + 4; - } - console.log('openblock StructData.Get 4 '+type+" "+id); - } - throw Error("找不到 ID为" + id + "的" + type); - } -} - -export class OBStructDataReader { - /** - * - * @param {OBArrayBufferReader} reader - * @returns {StructData} - */ - readStream(reader) { - let dataLength = reader.ReadUInt32(); - let data = reader.readSub(dataLength); - return this.readStructData(reader, data); - } - /** - * - * @param {OBArrayBufferReader} reader - * @param {OBArrayBufferReader} data - * @returns {StructData} - */ - readStructData(reader, data) { - let _length = reader.ReadInt32(); - let structs = {}; - - let groupCnt = reader.ReadUInt32(); - for (let i = 0; i < groupCnt; i++) { - let offset = reader.pos; - let strIdx = reader.ReadUInt32(); - let FullName = data.GetString(strIdx); - let structCnt = reader.ReadInt32(); - let length = reader.ReadInt32(); - // arraybuffer - let bin = reader.readSub(length * 4); - let info = new OBStructValueData(); // - info.Data = bin; - info.FullName = FullName; - info.Offset = offset; - info.Length = length; - info.StructCount = structCnt; - structs[FullName] = info; - } - return new StructData(structs, data); - } -} -class Relocation { - /** - * @1type {Object.:{idx:Number,inited:bool}>} - */ - string = {}; - /** - * @1type {Object.} - */ - integer = {}; - /** - * @1type {Object.} - */ - float = {}; - /** - * @1type {Object.} - */ - bin = {}; - /** - * @1type {Object.} - */ - structFieldIndex = {}; - - addRelocationString(str) { - if ((typeof str) !== 'string') { - throw Error('不是字符串'); - } - if (!this.string.hasOwnProperty(str)) { - this.string[str] = { - idx: 0, - inited: false - } - } - } -} -export class OBScriptLoader { - /** - * @type {OBArrayBufferReader} - */ - reader; //OBArrayBufferReader - /** - * @type {OBArrayBufferReader} - */ - data; //OBArrayBufferReader - loadingFunctions = {}; //[OBFunctionBuilder] - Linkings = []; //Linkable - - /** - * @callback NativeLibInstaller - * @param {OBScript} script - */ - /** - * - * @param {ArrayBuffer} arraybuffer of byte code - * @param {NativeLibInstaller} nativeLibs - * @returns - */ - static loadScript(arraybuffer, nativeLibs) { - let script = new OBScript(); - OBBuildInFunctions.install(script); - let l = new OBScriptLoader(); - // let nativeLibs = OBNative.functions; - if (nativeLibs) { - if (Array.isArray(nativeLibs)) { - nativeLibs.forEach(installer => { - installer(script); - }); - } else { - nativeLibs(script); - } - } - l.load(script, arraybuffer); - return script; - } - load(script, buf) { - this.script = script; - this.reader = new OBArrayBufferReader(buf); - this.readXE(); - } - - readXE() { - let MAG = this.reader.ReadInt32(); //'\u007fUEX'; - if (MAG != 0x5845557F) { - throw Error("Unknown MAG:" + MAG); - } - let version = this.reader.ReadUInt32(); - if (version != 1) { - throw Error("Unsupported version." + version); - } - - let SegmentCnt = this.reader.ReadUInt32(); - let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; - - let codes = []; - - for (let i = 0; i < SegmentCnt; i++) { - let type = this.reader.ReadUInt32(); - let startIn4Bytes = this.reader.ReadUInt32(); - let start = headerEnd + startIn4Bytes * 4; - let pos = this.reader.pos; - switch (type) { - case 0: - this.reader.seek(start); - this.data = this.loadDataSegment(); - break; - case 1: - this.reader.seek(start); - let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 - codes.push(code); - break; - case 2: - this.reader.seek(start); - this.script.StructData = this.loadStructDataSegment(); - this.script.StructData.StructDef = this.script.StructDef; - break; - case 3: - this.reader.seek(start); - this.script.StructDef = this.loadStructDefDataSegment(); - break; - case 4: - this.reader.seek(start); - this.loadPackageInfo(); - break; - default: - throw Error("Unknown Segment type:" + type); - } - this.reader.seek(pos); - } - this.script.loadedFunctions = this.loadingFunctions; - this.Linkings.forEach(l => { - l.link(); - }); - codes.forEach(codeSeg => { - codeSeg.fsms.forEach(fsm => { - fsm.FullName = codeSeg.name + "." + fsm.Name; - this.script.FullNameFSMData[fsm.FullName] = fsm; - }); - }); - } - - loadCodeSegment() { - let reader = this.reader; - let data = this.data; - - let start = reader.pos; - let SegmentReader = reader.getSub(start); - let length = SegmentReader.ReadUInt32(); - let header = SegmentReader.ReadUInt32() * 4; - SegmentReader.pos = header; - let segment = new OBCodeSegment(); - let nameStringIdx = SegmentReader.ReadInt32(); - let name = data.GetString(nameStringIdx); - let ufunctions = this.readFunctions(SegmentReader); - let fsms = this.readFSMs(SegmentReader, name); - // 字段赋值 - segment.name = name; - segment.functions = ufunctions; - segment.fsms = fsms; - return segment; - } - - readFSMs(reader, moduleName) { - let cnt = reader.ReadInt32(); - let f = []; // [OBFSM] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = s; - let fsm = this.readFSM(reader); - fsm.ModuleName = moduleName; - fsm.FullName = moduleName + "." + fsm.Name; - console.log('openblock fsm:'+fsm.FullName); - reader.pos = pos; - f[i] = fsm; - } - return f; - } - - readFSM(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - let fucCnt = reader.ReadUInt32(); - // TODO - let states = this.readStates(reader); - let entryStateNameIdx = reader.ReadUInt32(); - let entryStateName = data.GetString(entryStateNameIdx); - let entryState = null; - - // Dictionary stateDict = new Dictionary(); - let stateDict = {}; - for (let i = 0; i < states.length; i++) { - let s = states[i]; - stateDict[s.Name] = s; - if (entryStateName === s.Name) { - entryState = s; - } - } - if (entryState == null) { - throw Error("Can't find state named " + entryStateName + " FSM " + name); - } - let fsm = new OBFSM(); - fsm.Name = name; - fsm.States = stateDict; - fsm.Entry = entryState; - fsm.Variables = variables; - return fsm; - } - - readStates(reader) { - let cnt = reader.ReadInt32(); - let r = []; //[OBState] - for (let i = 0; i < cnt; i++) { - let s = reader.ReadUInt32() * 4; - let p = reader.pos; - reader.pos = s; - r.push(this.readState(reader)); - reader.pos = p; - } - return r; - } - - readState(reader) { - let data = this.data; - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let variables = this.readVariables(reader); - // 读取函数 - this.readFunctions(reader); - // UMessageHandler[] - let handlers = this.readHandlers(reader); - // UEventHandler[] - let ehandlers = this.readEHandlers(reader); - // Dictionary> Mh = new Dictionary>(); - let Mh = {}; - for (let i = 0; i < handlers.length; i++) { - let h = handlers[i]; - let hl = Mh[h.Name]; - if (hl) { - } else { - hl = []; //new List(); - Mh[h.Name] = hl; - } - hl.push(h); - } - // Dictionary eh = new Dictionary(); - let eh = {}; - for (let i = 0; i < ehandlers.length; i++) { - let h = ehandlers[i]; - eh[h.Name] = h; - } - let r = new OBState(); - r.Variables = variables; - r.Name = name; - r.MessageHandlers = Mh; - r.EventHandlers = eh; - return r; - } - - readEHandlers(reader) { - let cnt = reader.ReadInt32(); - // UEventHandler[] f = new UEventHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readEHandler(reader, start); - f[i] = h; - } - return f; - } - - readEHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBEventHandler(); - h.Name = func.Signure; - h.Func = func; - reader.pos = pos; - return h; - } - - readHandlers(reader) { - let cnt = reader.ReadUInt32(); - // UMessageHandler[] f = new UMessageHandler[cnt]; - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let h = this.readHandler(reader, start); - f[i] = h; - } - return f; - } - - readHandler(reader, start) { - let pos = reader.pos; - reader.pos = start; - let func = this.readFunction(reader); - let h = new OBMessageHandler(); - let pair = func.Signure.split(':'); - h.Name = pair[0]; - h.Func = func; - h.ArgTypeName = pair[1]; - reader.pos = pos; - return h; - } - - readVariables(reader) { - let data = this.data; - let varCnt = reader.ReadUInt32(); - // List d = new List(); - let d = []; - for (let i = 0; i < varCnt; i++) { - let v = this.readVariable(reader); - d.push(v); - } - return d; - } - - readVariable(reader) { - // let typeIdx = reader.ReadUInt32(); - // let count = reader.ReadInt32(); - let vari = reader.ReadUInt32(); - let count = vari & 0xFFFFFFF; - let typeIdx = vari >> 28; - let v = new OBVariableInfo(typeIdx, count); - return v; - } - - readFunctions(reader) { - let cnt = reader.ReadInt32(); - let f = []; - for (let i = 0; i < cnt; i++) { - let start = reader.ReadUInt32() * 4; - let pos = reader.pos; - reader.pos = start; - let _f = this.readFunction(reader); - f[i] = _f; - this.loadingFunctions[_f.Signure] = _f; - reader.pos = pos; - } - return f; - } - - readFunction(reader) { - let builder = new OBFunctionBuilder(this); - builder.loadFunctionHeader(reader); - builder.loadStatement(reader); - this.addLinking(builder); - let f = builder.build(); - return f; - } - - addLinking(l) { - this.Linkings.push(l); - } - - loadStructDataSegment() { - let reader = this.reader; - let data = this.data; - return new OBStructDataReader().readStructData(reader, data); - } - /** - * - * @returns {Object.} - */ - loadStructDefDataSegment() { - let reader = this.reader; - let data = this.data; - let length = reader.ReadUInt32(); - let d = {}; - let cnt = reader.ReadUInt32(); - for (let i = 0; i < cnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let typeCnt = reader.ReadUInt32(); - let structCnt = (typeCnt & 0x7F); - let stringCnt = ((typeCnt >> 7) & 0x7F); - let integerCnt = ((typeCnt >> 14) & 0x7F); - let floatCnt = ((typeCnt >> 21) & 0x7F); - let NobjectCnt = ((typeCnt >> 28)); - // string[] fields = new string[structCnt]; - let fields = []; - for (let j = 0; j < structCnt; j++) { - let fnameIdx = reader.ReadUInt32(); - let fname = data.GetString(fnameIdx); - fields[j] = fname; - } - let s = new OBStructDef(); - s.Name = name; - s.StructCnt = structCnt; - s.StringCnt = stringCnt; - s.IntegerCnt = integerCnt; - s.FloatCnt = floatCnt; - s.NobjectCnt = NobjectCnt; - s.StructFields = fields; - d[name] = s; - } - return d; - } - - loadDataSegment() { - let length = this.reader.ReadUInt32(); - return this.reader.readSub(length * 4); - } - - loadPackageInfo() { - let reader = this.reader; - let data = this.data; - let depCnt = reader.ReadUInt32(); - let err = []; - for (let i = 0; i < depCnt; i++) { - let nameIdx = reader.ReadUInt32(); - let name = data.GetString(nameIdx); - let hashIdx = reader.ReadUInt32(); - let hash = data.GetString(hashIdx); - let lhash = this.script.NativeLibHash[name]; - if (!lhash) { - err.push("No native lib named " + name); - } else if (lhash != hash) { - err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); - } - } - if (err.length > 0) { - // throw err; - console.error(err); - } - } -} - -export class OBArrayBufferReader { - /** - * @type {Number} integer of position - */ - pos; // int - /** - * @type {Number} integer of start - */ - start; // int - /** - * @type {ArrayBuffer} - */ - buf; // ArrayBuffer - /** - * @type DataView - */ - view; // DataView - /** - * @type {Object.} - */ - stringCache = {}; - - constructor(buf) { - this.buf = buf; - this.pos = 0; - this.start = 0; - this.view = new DataView(buf); - } - - ReadInt32() { - let v = this.getInt32(this.pos); - this.pos += 4; - return v; - } - - getInt32(p) { - let v = this.view.getInt32(this.start + p, true); - // let v = this.view.getInt32(p, true); - return v; - } - - ReadUInt32() { - let v = this.getUint32(this.pos); - this.pos += 4; - return v; - } - - getUint32(p) { - let v = this.view.getUint32(this.start + p, true); - // let v = this.view.getUint32(p, true); - return v; - } - - ReadSingle() { - let v = this.getFloat(this.pos); - return v; - } - - getFloat(p) { - let v = this.view.getFloat32(this.start + p, true); - // let v = this.view.getFloat32(p, true); - return v; - } - - GetString(stringIdx) { - let str = this.stringCache[stringIdx]; - if (str) { - return str; - } - let start = stringIdx * 8; // 字符串是8字节对齐 - let length = this.view.getUint32(this.start + start, true); - if (length === 0) { - return ""; - } - start = this.start + start + 4; - // start = start + 4; - let ab = this.buf.slice(start, start + length); - let ui8 = new Uint8Array(ab); - let utf8decoder = new util.TextDecoder("utf-8", { - fatal: true - }); - str = utf8decoder.decode(ui8); - if (str === null) { - throw Error('no string value of idx:' + stringIdx); - } - console.log('openblock getString '+str - + ' byteLength ' + ab.byteLength - + ' index ' + stringIdx - + ' Length ' + str.length); -// str = JSON.parse(JSON.stringify(str)); -// console.log('openblock getString after JSON '+str); - this.stringCache[stringIdx] = str; - return str; - } - - readSub(length) { - let v = this.getSub(this.pos, length); - this.pos += length; - return v; - } - - getSub(pos, length) { - // let buf; - // if (typeof (length) === "undefined") { - // buf = this.buf.slice(pos); - // } else { - // buf = this.buf.slice(pos, pos + length); - // } - // let reader = new OBArrayBufferReader(buf); - // reader.start = this.start + pos; - // return reader; - let reader = new OBArrayBufferReader(this.buf); - reader.start = this.start + pos; - return reader; - } - - seek(pos) { - if (typeof (pos) === "number") { - this.pos = pos; - } - return this.pos; - } - /** - * - * @param {Number} startIdx - * @returns {number[]} - */ - GetInt32FromBin(startIdx) { - let start = startIdx * 8; // 8字节对齐 - let p = this.pos; - this.pos = start; - let byteLength = this.ReadUInt32(); - let length = byteLength / 4; - let r = []; - for (let i = 0; i < length; i++) { - r.push(this.ReadInt32()); - } - this.pos = p; - return r; - } -} - - -export class OBStatementContext { - InstPos; - Actions = []; - - PushAction(Instruction) { - if(!Instruction){ - throw 'Instruction is null,2'; - } - this.Actions.push(Instruction); - } -} -// 虚拟机 - -export class VMInterruptException { -} -export class ChangeStateException extends VMInterruptException { -} -export class ChangeDestroyException extends VMInterruptException { -} -export class OBVM { - /** - * @1type {function(any)} - */ - Output; - setTimeout; - /** - * typeName->[VMFSM] - * @1type {Object.} - */ - Running = {}; - /** - * @type OBScript - */ - script; - /** - * @1type {OBVMFSM} - */ - Pending = []; - /** - * - * @param {OBScript} script - */ - constructor(script,config) { - if (!script) { - throw Error("Script is null"); - } - this.script = script; - if(config){ - Object.assign(this,config); - } - if(!this.setTimeout){ - this.setTimeout = setTimeout; - } - } - - CreateFSM(name) { - if (name == null) { - return null; - } - if (this.script == null) { - throw Error("Script is null"); - } - console.log('openblock typeof data '+ typeof(this.script.FullNameFSMData)); - let testobj = {"abc": 123} - console.log("openblock "+testobj.abc) - console.log("openblock "+this.script.FullNameFSMData["xfan1"]); - let fsmdata = this.script.FullNameFSMData[name]; - if (!fsmdata) { - console.log('openblock fsmdata '+fsmdata); - console.log('openblock notfound:'+name +" length:"+name.length + " line 1546"); - for(let key in this.script.FullNameFSMData){ - console.log('openblock fsmlist:'+key +" length:"+key.length+ " line 1548"); - console.log('openblock fsmname compare :'+(key === name)+ " line 1549"); - if(key===name){ - fsmdata = this.script.FullNameFSMData[key]; - let c = name==='1234567890'; - console.log('openblock fsmdata1 '+fsmdata + ","+c); - return fsmdata; - } - } - return null; - } - let uBFSM = new OBVMFSM(this, fsmdata); - let list = this.Running[name]; - if (!list) { - list = []; - this.Running[name] = list; - } - list.push(uBFSM); - return uBFSM; - } - - update() { - this._HandleOnePendingFSM(); - // let timestamp = Date.now(); - // JS不需要在VM中处理计划任务 - // this._HandleSchedulingTask(timestamp); - // this._InvokeScheduledTask(timestamp); - } - - _HandleOnePendingFSM() { - while (this.Pending.length > 0) { - let fsm = this.Pending.shift(); - if (fsm) { - let fsmname = fsm.data.Name; - fsm.HandleAllMessages(); - } - } - } - /** - * - * @param {OBVMFSM} fsm - */ - _AddPendingFSM(fsm) { - this.Pending.push(fsm); - } - - Log(v) { - console.log(v); - if (this.Output) { - this.Output(v); - } - } - /** - * - * @param {OBVMFSM} fsm - */ - DestroyFSM(fsm) { - let name = fsm.data.FullName; - let list = this.Running[name]; - if (list) { - let idx = list.findIndex((f) => f === fsm); - if (idx > -1) { - list.splice(idx, 1); - } - } - } - /** - * - * @param {OBUserMessage} userMessage - */ - BroadcastMessage(userMessage) { - Object.values(this.Running).forEach(l => { - for (let i = 0; i < l.length; i++) { - let f = l[i]; - if (f && f != userMessage.sender) { - f.PostMessage(userMessage); - } - } - }); - } - /** - * - * @param {number} millisecond wait time - * @param {*} callback - */ - Schedule(millisecond, callback) { - this.setTimeout(callback, millisecond, this); - } - - FindRunningFSMByType(typeFullName) { - return this.Running[typeFullName] || []; - } -} -export class OBVMFSM { - static ID_GEN = 0; - /** - * @type {any} - */ - Target; - /** - * @type {OBFSM} - */ - data; - id; - /** - * @type {OBVMState} - */ - CurrentState; - /** - * @type {OBVMState[]} - */ - StateStack = []; - /** - * @type {OBVM} - */ - VM; - Inbox = []; - PrioritizedInbox = []; - VariableGroup; - /** - * - * @param {OBVM} vm - * @param {OBFSM} data - */ - constructor(vm, data) { - this.data = data; - this.id = ++OBVMFSM.ID_GEN; - this.VM = vm; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.CurrentState = new OBVMState(data.Entry, this); - this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); - } - /** - * 推送高优先级消息 - * @param {OBMessage} msg - */ - PostPrioritizedMessage(msg) { - if (this.PrioritizedInbox == null) { - return; - } - this.PrioritizedInbox.push(msg); - this.VM._AddPendingFSM(this); - } - /** - * 推送消息 - * @param {OBMessage} msg - */ - PostMessage(msg) { - if (this.Inbox == null) { - return; - } - this.Inbox.push(msg); - this.VM._AddPendingFSM(this); - } - - HandleAllMessages() { - if (!this.CurrentState) { - return; - } - let msg; - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - while (msg = this.Inbox.shift()) { - msg.Handle(this.CurrentState); - while (msg = this.PrioritizedInbox.shift()) { - msg.Handle(this.CurrentState); - } - } - } - - Destroy() { - this.VariableGroup = null; - this.CurrentState = null; - this.Inbox.length = 0; - this.StateStack.length = 0; - this.PrioritizedInbox.length = 0; - this.VM.DestroyFSM(this); - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return this.CurrentState.IsListeningEvent(title); - } - - toString() { - return "FSM:" + this.data.FullName; - } - - ChangeState(name) { - - if (this.VM == null) { - return; - } - if (this.data.States[name]) { - this.CurrentState = new OBVMState(this.data.States[name], this); - this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); - } else { - throw Error("No state named " + name + " of FSM " + this.data.Name); - } - } -} -export class OBTypedVariableGroup { - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBVariableInfo[]} variables - */ - constructor(variables) { - if (!variables) { - return; - } - variables.forEach(v => { - switch (v.typeIdx) { - case 0: - if (this.LongRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.LongRegister = []; - this.LongRegister.length = v.count; - this.LongRegister.fill(0); - break; - case 1: - if (this.DoubleRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.DoubleRegister = []; - this.DoubleRegister.length = v.count; - this.DoubleRegister.fill(0); - break; - case 2: - if (this.StringRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StringRegister = []; - this.StringRegister.length = v.count; - this.StringRegister.fill(""); - break; - - case 3: - if (this.StructRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.StructRegister = []; - this.StructRegister.length = v.count; - break; - case 4: - if (this.NObjectRegister != null) { - throw Error("duplicated type " + v.typeIdx); - } - this.NObjectRegister = []; - this.NObjectRegister.length = v.count; - break; - default: - throw Error("Unknown type " + v.typeIdx); - } - }); - } -} -export class OBVMState { - /** - * @type {OBState} - */ - data; - /** - * @type {OBVMFSM} - */ - fsm; - /** - * @type {OBTypedVariableGroup} - */ - VariableGroup; - /** - * @type {OBMessage} - */ - currentMessage; - - constructor(data, fsm) { - this.data = data; - this.VariableGroup = new OBTypedVariableGroup(data.Variables); - this.fsm = fsm; - } - /** - * - * @param {OBMessage} msg - */ - HandleEvent(msg) { - try { - let msgname = msg.name; - let h = this.data.EventHandlers[msgname]; - if (h) { - this.currentMessage = msg; - let vmf = new OBVMFunction(h.Func); - vmf.Call(this); - } - } finally { - this.currentMessage = null; - } - } - - HandleMessage(m) { - this.currentMessage = m; - try { - let typeName = null; - if (m.arg != null) { - typeName = m.GetArgType(); - } - let mname = m.name; - let hl = this.data.MessageHandlers[mname]; - let self = this; - if (hl) { - hl.forEach(h => { -// let str_h = JSON.stringify(h); -// let hArgTypeName = JSON.parse( JSON.stringify( h.ArgTypeName)); - let hArgTypeName = h.ArgTypeName; -// let typeName1 = typeName; -// let b = hArgTypeName === typeName1; -// let b1 = hArgTypeName == typeName1; -// let l = hArgTypeName.length; -// let l1 = typeName1.length; -// let b2 = "Integer"==="Integer"; -// let b3 = hArgTypeName=="Integer"; -// let b4 = typeName1=="Integer"; -// -// let t = typeof(hArgTypeName); -// let t1 = typeof(typeName); -// let s1 = "Integer"; -// let s2 = "Integer"; -// let b5 = s1==s2; -// let b6 = s1===s2; - if (hArgTypeName === "" || hArgTypeName===typeName) { - let fd = h.Func; - let obvmf = new OBVMFunction(fd); - this.fsm.VM.Log("typeof obvmf.Call:"+typeof(obvmf.Call)); - this.fsm.VM.Log("method name:"+mname); - obvmf.Call(self); - } - }); - } - } finally { - this.currentMessage = null; - } - } - /** - * - * @param {string} title - * @returns bool - */ - IsListeningEvent(title) { - return !!this.data.EventHandlers[title]; - } - - ReceivedMessage() { - if (this.currentMessage) { - return this.currentMessage.arg; - } else { - throw Error("当前上下文没有消息可用"); - } - } - - CurrentMessageSender() { - if (this.currentMessage) { - return this.currentMessage.sender; - } else { - throw Error("当前上下文没有消息可用"); - } - } -} -export class OBVMFunction { - /** - * @type {OBFunction} - */ - data; - /** - * @type {OBTypedVariableGroup} - */ - LocalVar; - returnType = -1; - returnValue; - LongRegister; - DoubleRegister; - StringRegister; - StructRegister; - NObjectRegister; - /** - * - * @param {OBFunction} obfunc - */ - constructor(obfunc, builder, args) { - this.data = obfunc; - let LocalVar = new OBTypedVariableGroup(obfunc.Variables); - this.LocalVar = LocalVar; - if (builder) { - /** - * @1type {List>();} - */ - let LongRegister_ = []; - let DoubleRegister_ = [];// new List>(); - let StringRegister_ = [];// new List>(); - let StructRegister_ = [];// new List>(); - let NObjectRegister_ = [];//new List>(); - - for (let i = 1; i < args.length; i++) { - let arg = args[i]; - let Register = arg & 0xFFF; - let RegisterType = (arg >> 12) & 0xF; - - switch (RegisterType) { - case 0: - LongRegister_.push(builder.LongRegister[Register]); - break; - case 1: - DoubleRegister_.push(builder.DoubleRegister[Register]); - break; - case 2: - StringRegister_.push(builder.StringRegister[Register]); - break; - case 3: - StructRegister_.push(builder.StructRegister[Register]); - break; - case 4: - NObjectRegister_.push(builder.NObjectRegister[Register]); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } - if (LongRegister_.length > 0) { - this.LongRegister = LongRegister_; - } - if (DoubleRegister_.length > 0) { - this.DoubleRegister = DoubleRegister_; - } - if (StringRegister_.length > 0) { - this.StringRegister = StringRegister_; - } - if (StructRegister_.length > 0) { - this.StructRegister = StructRegister_; - } - if (NObjectRegister_.length > 0) { - this.NObjectRegister = NObjectRegister_; - } - } - } - /** - * - * @param {OBVMState} state - * @param {OBVMFunction} uBFunction - * @param {Object} localVars - */ - Call(state, uBFunction, localVars) { - if (uBFunction) { - if (this.LongRegister != null) { - for (let i = 0; i < this.LongRegister.length; i++) { - this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); - } - } - if (this.DoubleRegister != null) { - for (let i = 0; i < this.DoubleRegister.length; i++) { - this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); - } - } - if (this.StringRegister != null) { - for (let i = 0; i < this.StringRegister.length; i++) { - this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); - } - } - if (this.StructRegister != null) { - for (let i = 0; i < this.StructRegister.length; i++) { - this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); - } - } - if (this.NObjectRegister != null) { - for (let i = 0; i < this.NObjectRegister.length; i++) { - this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); - } - } - } - let Actions = this.data.Statements.Actions; - for (let i = 0; i < Actions.length && i >= 0;) { - let action = Actions[i]; - i = action(state, this, this.LocalVar, i); - } - } - - SetReturnLong(v) { - this.returnType = 1; - this.returnValue = v; - } - - Long() { - if (this.returnType === 1) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); - } - } - - SetReturnDouble(v) { - this.returnType = 2; - this.returnValue = v; - } - - Double() { - if (this.returnType === 2) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); - } - } - - SetReturnString(v) { - this.returnType = 3; - this.returnValue = v; - } - - String() { - if (this.returnType === 3) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); - } - } - - SetReturnStruct(v) { - this.returnType = 4; - this.returnValue = v; - } - - Struct() { - if (this.returnType === 4) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); - } - } - - SetReturnNObject(v) { - this.returnType = 5; - this.returnValue = v; - } - - NObject() { - if (this.returnType === 5) { - return this.returnValue; - } - else { - throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); - } - } -} -export class OBMessage { - name; - arg; - argType; - sender; - /** - * - * @param {string} name - * @param {string} argType - * @param {any} arg - * @param {?OBVMFSM} sender - */ - constructor(name, argType, arg, sender) { - this.name = name; - this.argType = argType; - this.arg = arg; - this.sender = sender; - } - - GetArgType() { - return this.argType; - } - - static ArgTypeOf(typeId, arg) { - switch (typeId) { - case 0xf: - return ""; - case 0: - return "Integer"; - case 1: - return "Number"; - case 2: - return "String"; - case 3: - return arg.Def.Name; - case 4: - // return "NObject"; - if (arg.constructor === OBVMFSM) { - return "FSM"; - } else { - if (arg.constructor) { - return arg.constructor.name; - } else { - return typeof (arg); - } - } - default: - throw Error("Unknown type:" + typeId); - } - } -} -export class OBEventMessage extends OBMessage { - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleEvent(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - state.fsm.VM.Log(err+""); - throw err; - } - } - } -} -export class OBUserMessage extends OBMessage { - - /** - * - * @param {OBVMState} state - */ - Handle(state) { - try { - state.HandleMessage(this); - } catch (err) { - if (!(err instanceof VMInterruptException)) { - state.fsm.VM.Log("Error:"+err); - throw err; - } - } - } -} -// 字节码 -export class LDSTR extends OBInstruction { - Value; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Value = builder.loader.data.GetString(stridx); - this.Register = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.StringRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - return this.Value; - } -} -export class PRT extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = (code & 0xF00000) >> 20; - this.RegisterIdx = code & 0xFFFFF; - } - - link(builder, instructions, idx) { - let v; - switch (this.RegisterType) { - case 0: - v = builder.LongRegister[this.RegisterIdx]; - break; - case 1: - v = builder.DoubleRegister[this.RegisterIdx]; - break; - case 2: - v = builder.StringRegister[this.RegisterIdx]; - break; - case 3: - v = builder.StructRegister[this.RegisterIdx]; - break; - case 4: - v = builder.NObjectRegister[this.RegisterIdx]; - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let val = v(st, uf, locals); - let vm = st.fsm.VM; - vm.Log(val); - return ++pos; - }); - } -} -export class ReceivedMessage extends OBInstruction { - typeId; - Register; - - init(code, builder, instructions, i) { - this.typeId = (code >> 20) & 0xf; - this.Register = code & 0xfffff; - } - - link(builder, instructions, idx) { - let Register = this.Register; - switch (this.typeId) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.ReceivedMessage(); - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - } -} -export class STVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - let stt = fst(st, uf, locals); - st.VariableGroup.StructRegister[VarIdx] = stt; - if (!stt) { - debugger - } - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } -} -export class STVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return st.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } -} -export class StructFieldDesc extends OBInstruction { - fieldTypeId; - fieldDescIdx; - - init(code, builder, instructions, i) { - this.fieldDescIdx = code & 0xfffff; - this.fieldTypeId = (code >> 20) & 0xf; - } -} -export class GetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - - case 0: - builder.LongRegister[Register] = (st, uf, locals) => { - let stt = getStruct(st, uf, locals); - return stt.registers.LongRegister[fieldIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, locals) => { - return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; - }; - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } -} -export class SetStructField extends OBInstruction { - structIdx; - Register; - typeId; - fieldIdx; - - init(code, builder, instructions, i) { - let desc = instructions[i - 1]; - if (!(desc instanceof StructFieldDesc)) { - throw Error("last cmd is not StructFieldDesc"); - } - this.structIdx = (code >> 12) & 0xfff; - this.Register = (code) & 0xfff; - this.typeId = desc.fieldTypeId; - this.fieldIdx = desc.fieldDescIdx; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let fieldIdx = this.fieldIdx; - let getStruct = builder.StructRegister[this.structIdx]; - switch (this.typeId) { - case 0: - let getLong = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); - return ++pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); - return ++pos; - }); - break; - case 2: - let GetString = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); - return ++pos; - }); - break; - case 3: - let getStruct1 = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); - return ++pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + this.typeId); - } - - } -} -export class CHSTT extends OBInstruction { - StateName; - - init(code, builder, instructions, i) { - let strIdx = (code & 0xFFFFFF); - let str = builder.loader.data.GetString(strIdx); - this.StateName = str; - } - - link(builder, instructions, idx) { - builder.PushAction((state, uf, locals, pos) => { - state.fsm.ChangeState(this.StateName); - throw new ChangeStateException(); - //return ++pos; - }); - } -} -export class MethodCallRegisterInfoAnchor extends OBInstruction { - RegisterInfoIdx; - - init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; - } -} -export class NativeMethodCall extends OBInstruction { - LibNameIdx; - - init(code, builder, instructions, i) { - this.LibNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let LibName = builder.loader.data.GetString(this.LibNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - let funcIdx = args[0]; - let _args = args.slice(1); - let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); - installer(builder, _args); - } -} -export class FSMVS extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let Register = this.Register; - let VarIdx = this.VarIdx; - let RegisterType = this.RegisterType; - switch (RegisterType) { - case 0: - let fl = builder.LongRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); - return ++pos; - }); - break; - case 1: - let fd = builder.DoubleRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); - return ++pos; - }); - break; - case 2: - let fs = builder.StringRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); - return ++pos; - }); - break; - case 3: - let fst = builder.StructRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); - return ++pos; - }); - break; - case 4: - let fo = builder.NObjectRegister[Register]; - builder.PushAction((st, uf, locals, pos) => { - st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); - return ++pos; - }); - break; - default: - throw Error("Unknown type " + RegisterType); - } - } -} -export class SLF extends OBInstruction { - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterIdx = code & 0xffffff; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { - return s.fsm; - }; - } -} -export class MethodCall extends OBInstruction { - MethodNameIdx; - - init(code, builder, instructions, i) { - this.MethodNameIdx = code & 0xFFFFFF; - } - - link(builder, instructions, idx) { - let MethodName = builder.loader.data.GetString(this.MethodNameIdx); - let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); - } - let RegisterInfoIdx = anchor.RegisterInfoIdx; - let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); - - let uf1 = builder.loader.script.loadedFunctions[MethodName]; - if (uf1 != null) { - // 参数 - let f = new OBVMFunction(uf1, builder, args); - let returnRegister = args[0]; - if (returnRegister === -1) { - builder.PushAction((state, uf, localVars, pos) => { - f.Call(state, f, localVars); - return ++pos; - }); - } else { - let Register = returnRegister & 0xFFF; - let registerType = (returnRegister >> 12) & 0xF; - // 处理有返回值的情况 - switch (registerType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Long(); - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Double(); - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.String(); - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.Struct(); - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - f.Call(st, uf, l); - return f.NObject(); - }; - break; - default: - throw Error("Unknown type " + registerType); - } - } - } else { - throw Error("未找到函数 " + MethodName); - } - } -} -export class BRIFN extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - targetOffsetBak; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); - this.targetOffsetBak = this.targetOffset; - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) === 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str == null || ("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) == null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + checkRegType); - } - } -} -export class BR extends OBInstruction { - Offset; - - init(code, builder, instructions, i) { - this.Offset = ((code << 8) >> 8); - builder.PositionUpdate(this.Offset * 4, (newPos) => { - this.Offset = newPos; - }); - } - - link(builder, instructions, idx) { - builder.PushAction((ub, uf, locals, pos) => { - return this.Offset; - }); - } -} -export class NOP extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - return pos + 1; - }); - } -} -export class ARITHF extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.DoubleRegister[this.LeftRegister]; - let right = builder.DoubleRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l / r; - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.pow(l, r); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.DoubleRegister[this.LeftRegister] = o; - } -} - -export class ARITHI extends OBInstruction { - Opcode; - LeftRegister; - RightRegister; - - init(code, builder, instructions, i) { - this.LeftRegister = (code >> 10) & 0x3FF; - this.RightRegister = (code & 0x3FF); - this.Opcode = (code >> 20) & 0xf; - } - - link(builder, instructions, idx) { - let left = builder.LongRegister[this.LeftRegister]; - let right = builder.LongRegister[this.RightRegister]; - if (left == null) { - throw Error("left is null"); - } - if (right == null) { - throw Error("right is null"); - } - let o; - switch (this.Opcode) { - case 0: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l + r; - } - break; - case 1: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l - r; - } - break; - case 2: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l * r; - } - break; - case 3: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(l / r); - } - break; - case 4: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return Math.floor(Math.pow(l, r)); - } - break; - case 5: - o = (st, f, locals) => { - var l = left(st, f, locals); - var r = right(st, f, locals); - return l % r; - } - break; - default: - throw Error("未知操作符 " + this.Opcode); - } - builder.LongRegister[this.LeftRegister] = o; - } -} -export class LDI extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let pos = code & 0xFFF; - this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.LongRegister[this.Register] = () => { - return this.Value; - }; - } -} -export class LDF extends OBInstruction { - Register; - Value; - - init(code, builder, instructions, i) { - let specal = code & 0xFFFF; - switch (specal) { - case 0xFFFE: - this.Value = Number.POSITIVE_INFINITY; - break; - case 0xFFFD: - this.Value = Number.NEGATIVE_INFINITY; - break; - case 0xFFFF: - this.Value = Number.NaN; - break; - default: - this.Value = builder.loader.data.getFloat(specal * 4); - break; - } - this.Register = ((code & 0xFF0000) >> 16); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = () => { - return this.Value; - }; - } -} -export class RET extends OBInstruction { - RegisterType; - RegisterIdx; - - init(code, builder, instructions, i) { - this.RegisterType = ((code & 0xF00000) >> 20); - this.RegisterIdx = (code & 0xFFFFF); - } - - link(builder, instructions, idx) { - switch (this.RegisterType) { - case 0: - let l = builder.LongRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = l(st, uf, locals); - uf.SetReturnLong(v); - return -1; - }); - break; - case 1: - let f = builder.DoubleRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - let v = f(st, uf, locals); - uf.SetReturnDouble(v); - return -1; - }); - break; - case 2: - let s = builder.StringRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(s(st, uf)); - let v = s(st, uf, locals); - uf.SetReturnString(v); - return -1; - }); - break; - case 3: - let u = builder.StructRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(u(st, uf)); - let v = u(st, uf, locals); - uf.SetReturnStruct(v); - return -1; - }); - break; - case 4: - let n = builder.NObjectRegister[this.RegisterIdx]; - builder.PushAction((st, uf, locals, pos) => { - //Console.WriteLine(n(st, uf)); - let v = n(st, uf, locals); - uf.SetReturnNObject(v); - return -1; - }); - break; - case 0xf: - builder.PushAction((st, uf, locals, pos) => { - return -1; - }); - break; - default: - throw Error("Unknown type:" + this.RegisterType); - } - } -} -export class FSMVG extends OBInstruction { - Register; - VarIdx; - RegisterType; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFF00) >> 8; - this.RegisterType = (code & 0xFF0000) >> 16; - this.VarIdx = code & 0xFF; - } - - link(builder, instructions, idx) { - let VarIdx = this.VarIdx; - let Register = this.Register; - switch (this.RegisterType) { - case 0: - builder.LongRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.LongRegister[VarIdx]; - }; - break; - case 1: - builder.DoubleRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.DoubleRegister[VarIdx]; - }; - break; - case 2: - builder.StringRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StringRegister[VarIdx]; - }; - break; - case 3: - builder.StructRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.StructRegister[VarIdx]; - }; - break; - case 4: - builder.NObjectRegister[Register] = (st, uf, l) => { - return st.fsm.VariableGroup.NObjectRegister[VarIdx]; - }; - break; - default: - throw Error("Unknown type " + this.RegisterType); - } - } -} -export class CreateFSM extends OBInstruction { - FSMTypeName; - ReturnRegister; - - init(code, builder, instructions, i) { - let FSMTypeNameIdx = code & 0xFFFF; - this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); - this.ReturnRegister = (code & 0xFF0000) >> 16; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { - let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); - if (!fsm) { - st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); - } else { - fsm.Target = st.fsm.Target; - } - return fsm; - }; - } -} -export class FSMSendMsg extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let f_fsm = builder.NObjectRegister[this.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let fsm = f_fsm(st, uf, locals); - if (fsm) { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - } - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - let BodyRegisterIdx = this.BodyRegisterIdx; - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} -export class GZ0 extends OBInstruction { - VarType; - VarIdx; - ResultIdx; - - init(code, builder, instructions, i) { - this.VarType = ((code >> 20) & 0xf); - this.VarIdx = ((code >> 10) & 0x3ff); - this.ResultIdx = (code & 0x3ff); - } - - link(builder, instructions, idx) { - let ResultIdx = this.ResultIdx; - let VarIdx = this.VarIdx; - switch (this.VarType) { - case 0: - let getLong = builder.LongRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - let lv = getLong(st, uf, locals); - return lv > 0 ? 1 : 0; - }; - break; - case 1: - let getDouble = builder.DoubleRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getDouble(st, uf, locals) > 0 ? 1 : 0; - }; - break; - case 2: - let GetString = builder.StringRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return GetString(st, uf, locals) != null ? 1 : 0; - }; - break; - case 3: - let getStruct = builder.StructRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getStruct(st, uf, locals) != null ? 1 : 0; - }; - break; - case 4: - let getNObject = builder.NObjectRegister[VarIdx]; - builder.LongRegister[ResultIdx] = (st, uf, locals) => { - return getNObject(st, uf, locals) == null ? 1 : 0; - }; - break; - default: - throw Error("Unknown type " + this.VarType); - } - } -} - -export class BRIF extends OBInstruction { - checkRegType; - checkRegIdx; - targetOffset; - - init(code, builder, instructions, i) { - this.checkRegType = ((code >> 20) & 0xf); - this.checkRegIdx = ((code >> 14) & 0x7f); - this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); - builder.PositionUpdate(this.targetOffset * 4, (newPos) => { - this.targetOffset = newPos; - }); - } - - link(builder, instructions, idx) { - let checkRegType = this.checkRegType; - let checkRegIdx = this.checkRegIdx; - switch (checkRegType) { - case 0: - let LongReg = builder.LongRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (LongReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 1: - let DoubleReg = builder.DoubleRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (DoubleReg(st, uf, locals) != 0) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 2: - let StringReg = builder.StringRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - let str = StringReg(st, uf, locals); - if (str != null && !("" === (str))) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 3: - let StructReg = builder.StructRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (StructReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - case 4: - let NObjectReg = builder.NObjectRegister[checkRegIdx]; - builder.PushAction((st, uf, locals, pos) => { - if (NObjectReg(st, uf, locals) != null) { - return this.targetOffset; - } else { - return ++pos; - } - }); - break; - default: - throw Error("Unknown type " + this.checkRegType); - } - } -} -export class DEC extends OBInstruction { - regType; - regIdx; - - init(code, builder, instructions, i) { - this.regType = ((code >> 20) & 0xf); - this.regIdx = ((code) & 0xfffff); - } - - link(builder, instructions, idx) { - let regIdx = this.regIdx; - switch (this.regType) { - case 0: - let LongReg = builder.LongRegister[regIdx]; - builder.LongRegister[regIdx] = (st, uf, locals) => { - let v = LongReg(st, uf, locals); - return v - 1; - }; - break; - case 1: - let DoubleReg = builder.DoubleRegister[regIdx]; - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - let v = DoubleReg(st, uf, locals); - return v - 1; - }; - break; - case 2: - case 3: - case 4: - default: - throw Error("Unsupport type " + this.regType); - } - } -} -export class Reg2Var extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - let getLong = builder.LongRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.LongRegister[varIdx] = getLong(st, uf, locals); - return 1 + pos; - }); - break; - case 1: - let getDouble = builder.DoubleRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); - return 1 + pos; - }); - break; - case 2: - let GetString = builder.StringRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StringRegister[varIdx] = GetString(st, uf, locals); - return 1 + pos; - }); - break; - case 3: - let getStruct = builder.StructRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.StructRegister[varIdx] = getStruct(st, uf, locals); - return 1 + pos; - }); - break; - case 4: - let getNObject = builder.NObjectRegister[regIdx]; - builder.PushAction((st, uf, locals, pos) => { - locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); - return 1 + pos; - }); - break; - default: - throw Error("Unsupport type:" + this.type); - } - } -} -export class Var2Reg extends OBInstruction { - type; - varIdx; - regIdx; - - init(code, builder, instructions, i) { - this.type = ((code >> 20) & 0xf); - this.regIdx = ((code >> 10) & 0x3ff); - this.varIdx = ((code) & 0x3ff); - } - - link(builder, instructions, idx) { - let varIdx = this.varIdx; - let regIdx = this.regIdx; - switch (this.type) { - case 0: - builder.LongRegister[regIdx] = (st, uf, locals) => { - return locals.LongRegister[varIdx]; - }; - break; - case 1: - builder.DoubleRegister[regIdx] = (st, uf, locals) => { - return locals.DoubleRegister[varIdx]; - }; - break; - case 2: - builder.StringRegister[regIdx] = (st, uf, locals) => { - return locals.StringRegister[varIdx]; - }; - break; - case 3: - builder.StructRegister[regIdx] = (st, uf, locals) => { - return locals.StructRegister[varIdx]; - }; - break; - case 4: - builder.NObjectRegister[regIdx] = (st, uf, locals) => { - return locals.NObjectRegister[varIdx]; - }; - break; - default: - throw Error("Unsupport type:" + this.type); - } - } -} -export class I2F extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let getLong = builder.LongRegister[this.intRegIdx]; - builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { - return getLong(st, uf, locals); - }; - } -} -export class EQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class NEQ extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - /** - * - * @param {OBFunctionBuilder} builder - * @param {*} instructions - * @param {*} idx - */ - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - break; - case 3: - regArr = builder.StructRegister; - break; - case 4: - regArr = builder.NObjectRegister; - ; - break; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class LT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class LTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class GT extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; - }; - } -} - -export class GTE extends OBInstruction { - ArgTypeId; - LeftIdx; - RightIdx; - RetIdx; - - init(code, builder, instructions, i) { - this.ArgTypeId = (code >> 20) & 0xF; - this.LeftIdx = (code >> 14) & 0x3f; - this.RightIdx = (code >> 7) & 0x7f; - this.RetIdx = code & 0x7f; - } - - link(builder, instructions, idx) { - let regArr; - switch (this.ArgTypeId) { - case 0: - regArr = builder.LongRegister; - break; - case 1: - regArr = builder.DoubleRegister; - break; - case 2: - regArr = builder.StringRegister; - return; - default: - throw Error("不支持类型:" + this.ArgTypeId); - } - let LeftReg = regArr[this.LeftIdx]; - let RightReg = regArr[this.RightIdx]; - builder.LongRegister[this.RetIdx] = (st, uf, locals) => { - return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; - }; - } -} -export class DestroyFSM extends OBInstruction { - link(builder, instructions, idx) { - builder.PushAction((st, uf, locals, pos) => { - st.fsm.Destroy(); - throw new ChangeDestroyException(); - }); - } -} -export class FSMBroadcastMsg extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); - return ++pos; - }); - } - /** - * - * @param {OBFunctionBuilder} builder - * @returns - */ - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} - -/** - * 单元数操作 - */ -export class SGLF extends OBInstruction { - Opcode; - value; - - init(code, builder, instructions, i) { - this.value = (code & 0xFFFF); - this.Opcode = (code >> 16) & 0xff; - } - - link(builder, instructions, idx) { - let value = this.value; - let f_value = builder.DoubleRegister[this.value]; - if (f_value == null) { - throw Error("left is null"); - } - switch (this.Opcode) { - case 0: - builder.DoubleRegister[value] = (s, f, l) => { - return -f_value(s, f, l); - }; - break; - case 1: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log(f_value(s, f, l)); - }; - break; - case 2: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.log10(f_value(s, f, l)); - }; - break; - case 3: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.exp(f_value(s, f, l)); - }; - break; - case 4: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.pow(10, f_value(s, f, l)); - }; - break; - case 5: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sqrt(f_value(s, f, l)); - }; - break; - case 6: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.abs(f_value(s, f, l)); - }; - break; - case 7: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.sin(f_value(s, f, l)); - }; - break; - case 8: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.cos(f_value(s, f, l)); - }; - break; - case 9: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.tan(f_value(s, f, l)); - }; - break; - case 10: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.asin(f_value(s, f, l)); - }; - break; - case 11: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.acos(f_value(s, f, l)); - }; - break; - case 12: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.atan(f_value(s, f, l)); - }; - break; - case 13: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.round(f_value(s, f, l)); - }; - break; - case 14: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.ceil(f_value(s, f, l)); - }; - break; - case 15: - builder.DoubleRegister[value] = (s, f, l) => { - return Math.floor(f_value(s, f, l)); - }; - break; - } - } -} -export class RAND extends OBInstruction { - Register; - - init(code, builder, instructions, i) { - this.Register = (code & 0xFFFFFF); - } - - link(builder, instructions, idx) { - builder.DoubleRegister[this.Register] = (st, f, l) => { - return Math.random(); - }; - } -} -export class F2I extends OBInstruction { - intRegIdx; - floatRegIdx; - - init(code, builder, instructions, i) { - this.intRegIdx = ((code) >> 12) & 0xFFF; - this.floatRegIdx = ((code) & 0xFFF); - } - - link(builder, instructions, idx) { - let g = builder.DoubleRegister[this.floatRegIdx]; - builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { - return Math.trunc(g(st, uf, locals)); - }; - } -} -export class FSMSendMsgWait_Data extends OBInstruction { - TitleIdx; - TargetIdx; - BodyTypeID; - BodyRegisterIdx; - - init(code, builder, instructions, i) { - this.TargetIdx = ((code >> 17) & 0x7F); - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - this.BodyRegisterIdx = (code & 0x3F); - } -} -export class FSMSendMsgWait extends OBInstruction { - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - } - - link(builder, instructions, idx) { - let anchor = instructions[idx - 1]; - if (!(anchor instanceof FSMSendMsgWait_Data)) { - throw Error("字节码错误"); - } - let f_title = builder.StringRegister[anchor.TitleIdx]; - let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let FSM = st.fsm; - let fsm = f_fsm(st, uf, locals); - if (!fsm) { - FSM.VM.Log("未找到发送目标"); - return; - } - if (!(fsm instanceof OBVMFSM)) { - throw Error("字节码错误"); - } - fsm.VM.Schedule(waitSecond, (VM) => { - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); - }); - return ++pos; - }); - } - - makeBody(builder, BodyTypeID, BodyRegisterIdx) { - switch (BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + BodyTypeID); - } - } -} -export class FSMBroadcastMsgWait extends OBInstruction { - TitleIdx; - BodyTypeID; - BodyRegisterIdx; - waitMilliSecondIdx; - - init(code, builder, instructions, i) { - this.TitleIdx = ((code >> 10) & 0x7F); - this.BodyTypeID = ((code >> 6) & 0xF); - - this.BodyRegisterIdx = (code & 0x3F); - this.waitMilliSecondIdx = ((code >> 17) & 0x3F); - ; - } - - link(builder, instructions, idx) { - let f_title = builder.StringRegister[this.TitleIdx]; - let f_body = this.makeBody(builder); - let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; - builder.PushAction((st, uf, locals, pos) => { - let title = f_title(st, uf, locals); - let body = f_body(st, uf, locals); - let waitSecond = waitTime(st, uf, locals); - let fsm = st.fsm; - fsm.VM.Schedule(waitSecond, (VM) => { - VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); - }); - return ++pos; - }); - } - - makeBody(builder) { - switch (this.BodyTypeID) { - case 0xF: - return (st, uf, locals) => null; - case 0: - var l = builder.LongRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return l(st, uf, locals); - }; - case 1: - var d = builder.DoubleRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return d(st, uf, locals); - }; - case 2: - var s = builder.StringRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s(st, uf, locals); - }; - case 3: - var s1 = builder.StructRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return s1(st, uf, locals); - }; - case 4: - var n = builder.NObjectRegister[this.BodyRegisterIdx]; - return (st, uf, locals) => { - return n(st, uf, locals); - }; - default: - throw Error("Unknown type " + this.BodyTypeID); - } - } -} -export class TextJoin extends OBInstruction { - Left; - Right; - RetReg; - - init(code, builder, instructions, i) { - this.Left = (code >> 17) & 0xFF; - this.Right = (code >> 9) & 0xff; - this.RetReg = (code & 0xFF); - } - - link(builder, instructions, idx) { - var l = builder.StringRegister[this.Left]; - var r = builder.StringRegister[this.Right]; - builder.StringRegister[this.RetReg] = (st, f, local) => { - return l(st, f, local) + r(st, f, local); - }; - } -} -export class ToString extends OBInstruction { - ValueType; - ValueRegIdx; - RetRegIdx; - - init(code, builder, instructions, i) { - this.ValueType = (code >> 20) & 0xF; - this.ValueRegIdx = (code >> 10) & 0x1ff; - this.RetRegIdx = (code & 0x1FF); - } - - link(builder, instructions, idx) { - switch (this.ValueType) { - case 0: - var getl = builder.LongRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getl(st, f, l).toString(); - }; - break; - case 1: - var getd = builder.DoubleRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - return getd(st, f, l).toString(); - }; - break; - case 2: - var getstr = builder.StringRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstr(st, f, l); - if (v == null) { - return ""; - } - return v; - }; - break; - case 3: - var getstruct = builder.StructRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = getstruct(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - case 4: - var geto = builder.NObjectRegister[this.ValueRegIdx]; - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - var v = geto(st, f, l); - if (v == null) { - return ""; - } - return v.toString(); - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } -} -export class Sender extends OBInstruction { - RetReg; - - init(code, builder, instructions, i) { - this.RetReg = code & 0xFFFF; - } - - link(builder, instructions, idx) { - builder.NObjectRegister[this.RetReg] = (st, f, local) => { - return st.CurrentMessageSender(); - }; - } -} -export class SHL extends OBInstruction { - value; bitCount; - init(code, builder, instructions, i) { - this.bitCount = code & 0xFFF; - this.value = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.value]; - let getC = builder.LongRegister[this.bitCount]; - builder.LongRegister[this.value] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - if (c > 0) { - let r = v << c; - return r; - } else { - let r = v >> -c; - return r; - } - - }; - } -} -export class AND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - let c = getC(st, f, l); - let r = v & c; - return r; - }; - } -} -export class FIX extends OBInstruction { - regType; regIdx; - init(code, builder, instructions, i) { - this.regIdx = code & 0xFFFFF; - this.regType = (code & 0xF00000) >> 20; - } - link(builder, instructions, idx) { - let v; - let loaded = false; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - let getV = builder[type][this.regIdx]; - builder[type][this.regIdx] = (st, f, l) => { - if (!loaded) { - v = getV(st, f, l); - } else { - loaded = true; - } - return v; - }; - } -} -/** - * value of may by key - */ -export class VOM extends OBInstruction { - map; - key; - ValueType; - RetRegIdx; - init(code, builder, instructions, i) { - this.ValueType = code & 0x3F; - this.RetRegIdx = (code & (0x3f << 6)) >> 6; - this.key = (code & (0x3f << 12)) >> 12; - this.map = (code & (0x3f << 18)) >> 18; - } - - link(builder, instructions, idx) { - var getMap = builder.StructRegister[this.map]; - var getKey = builder.StringRegister[this.key]; - switch (this.ValueType) { - case 0: - builder.LongRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 1: - builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 2: - builder.StringRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - case 3: - builder.StructRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - if (!v) { - debugger - } - return v; - }; - break; - case 4: - builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { - let m = getMap(st, f, l); - let k = getKey(st, f, l); - let v = m[k]; - return v; - }; - break; - default: - throw Error("Unknown type:" + this.ValueType); - } - } -} -export class LAND extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - let c = getC(st, f, l); - return c ? 1 : 0; - } else { - return 0; - } - }; - } -} -export class LOR extends OBInstruction { - a; b; - init(code, builder, instructions, i) { - this.b = code & 0xFFF; - this.a = (code & 0xFFF000) >> 12; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - let getC = builder.LongRegister[this.b]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - if (v) { - return 1; - } else { - let c = getC(st, f, l); - return c ? 1 : 0; - } - }; - } -} -export class LNOT extends OBInstruction { - a; - init(code, builder, instructions, i) { - this.a = code & 0xFFF; - } - link(builder, instructions, idx) { - let getV = builder.LongRegister[this.a]; - builder.LongRegister[this.a] = (st, f, l) => { - let v = getV(st, f, l); - return v === 0 ? 1 : 0; - }; - } -} -export class COND extends OBInstruction { - if_; then_; else_; regType; - init(code, builder, instructions, i) { - this.regType = code & 0x3F; - this.else_ = (code & (0x3f << 6)) >> 6; - this.then_ = (code & (0x3f << 12)) >> 12; - this.if_ = (code & (0x3f << 18)) >> 18; - } - link(builder, instructions, idx) { - let if_ = builder.LongRegister[this.if_]; - let else_; - let then_; - let type; - switch (this.regType) { - case 0: - type = 'LongRegister'; - break; - case 1: - type = 'DoubleRegister'; - break; - case 2: - type = 'StringRegister'; - break; - case 3: - type = 'StructRegister'; - break; - case 4: - type = 'NObjectRegister'; - break; - default: - throw Error("Unknown type:" + this.regType); - } - else_ = builder[type][this.else_]; - then_ = builder[type][this.then_]; - builder[type][this.then_] = (st, f, l) => { - let if_v = if_(st, f, l); - if (if_v != 0) { - return then_(st, f, l); - } - return else_(st, f, l); - }; - } -} -export class NEW extends OBInstruction { - StructDef; - Register; - - init(code, builder, instructions, i) { - let stridx = code & 0xFFF; - this.Register = (code & 0xFF0000) >> 16; - - let structType = builder.loader.data.GetString(stridx); - let structDef = builder.loader.script.StructDef[structType]; - if (!structDef) { - throw Error('不存在数据结构 ' + structType); - } - this.StructDef = structDef; - } - - link(builder, instructions, idx) { - builder.StructRegister[this.Register] = this.getValue.bind(this); - } - - getValue(UBState, obvmfunction, TypedRegisters) { - let s = new OBStructValue(this.StructDef); - return s; - } -} + "use strict" + import * as util from './util.js' + // const util = require('./util.mjs'); + + class NativeUtil { + + static fieldSetter(target, fieldName, register) { + return (builder, args) => { + let getter = builder[register][args[1] & 0xfff]; + builder.PushAction((st, f, local, pos) => { + let v = getter(st, f, local); + target[fieldName] = v; + return 1 + pos; + }); + }; + } + static fieldGetter(target, fieldName, register) { + return (builder, args) => { + builder[register][args[1] & 0xfff] = (st, f, local) => { + return target[fieldName]; + }; + }; + } + static objFieldGetter(fieldName, fieldRegister) { + return (builder, args) => { + let obj = builder.NObjectRegister[args[1] & 0xfff]; + builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { + return obj(st, f, local)[fieldName]; + }; + }; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureVoid(func, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + if (typeof (v) != 'function') { + debugger + } + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder.PushAction((st, f, local, pos) => { + let argVals = argGetters.map(g => g(st, f, local)); + func.apply(null, argVals); + return pos + 1; + }); + }; + return f; + } + /** + * + * @param {Function} func + * @param {Number[]} argtype + * @returns + */ + static closureReturnValue(func, retRegisterType, argtype) { + /** + * + * @param {OBFunctionBuilder} builder + * @param {Number[]} args + * @returns + */ + let f = (builder, args) => { + let retRegIdx = args[0]; + let retType = (retRegIdx & 0xF000) >> 12; + retRegIdx = retRegIdx & 0xFFF; + args = args.slice(1); + let argGetters = argtype.map((rtype, idx) => { + let idx1 = args[idx] & 0xFFF; + let v = builder[rtype][idx1]; + return (st, f, local) => { + return v(st, f, local); + }; + }); + builder[retRegisterType][retRegIdx] = ((st, f, local) => { + let argVals = argGetters.map(g => g(st, f, local)); + return func.apply(null, argVals); + }); + }; + return f; + } + } + class OBScript { + constructor() { + + this.NativeLibHash = {}; // libname->hash + this.InstalledLibs = {}; + this.NativeUtil = NativeUtil; + /** + * @1type {StructData} + */ + this.StructData = {}; //typename->OBStructValueData + /** + * @type {Object.} + */ + this.StructDef = {}; // typename-> def + this.loadedFunctions; //= {};//function sign->function + this.FullNameFSMData = {}; //FullName->OBFSM + } + /** + * @callback FuncInstaller + * @param {OBFunctionBuilder} funcBuilder + * @param {number[]} registersConfig + */ + /** + * 安装本地库 + * @param {string} libName + * @param {string} jsmd5 md5 of js generated config + * @param {FuncInstaller[]} funcInstallers array of funcInstaller + */ + InstallLib(libName, jsmd5, funcInstallers) { + if (this.InstalledLibs[libName]) { + throw Error("重复导入 " + libName); + } + this.InstalledLibs[libName] = funcInstallers; + this.NativeLibHash[libName] = jsmd5; + } + /** + * + * @param {string} libname + * @param {number} funcIdx + */ + getNativeFunc(libname, funcIdx) { + if (funcIdx < 0) { + throw Error("funcIdx:" + funcIdx); + } + // Action < UFunctionBuilder, int[] > [] lib; + let lib = this.InstalledLibs[libname]; + if (lib) { + if (funcIdx < lib.length) { + return lib[funcIdx]; + } else { + throw Error("funcIdx:" + funcIdx + " of lib " + libname + " out of range " + lib.length); + } + } else { + throw Error("Native lib " + libname + " not found"); + } + } + } + class OBStructDef { + constructor() { + + this.Name; //string + this.StructCnt; // int + this.StringCnt; // int + this.IntegerCnt; // int + this.FloatCnt; // int + this.NobjectCnt; // int + this.StructFields; // int + } + } + class OBStructValueData { + // /** + // * @type {OBArrayBufferReader} + // */ + // Data; //arraybuffer + // FullName; + // Offset; + // Length; + // StructCount; + } + class OBVariableInfo { + // typeIdx; + // count; + + constructor(typeIdx, count) { + this.typeIdx = typeIdx; + this.count = count; + } + } + class OBState { + // /** + // * @type {OBVariableInfo[]} + // */ + // Variables; + // /** + // * @type {string} + // */ + // Name; + // MessageHandlers; + // EventHandlers; + } + class OBCodeSegment { + // name; + // functions; + // fsms; + } + class OBFunction { + // /** + // * @type {OBVariableInfo[]} + // */ + // Variables; + // instructions; + // /** + // * @type {String} + // */ + // Signure; + // Statements; + } + class OBFSM { + // /** + // * @type {string} + // */ + // Name; + // /** + // * @type {Object.} + // */ + // States; //string->state + // /** + // * @type {OBState} + // */ + // Entry; //state + // /** + // * @type {OBVariableInfo[]} + // */ + // Variables; + // /** + // * @type {string} + // */ + // FullName; + // /** + // * @type {string} + // */ + // ModuleName; + } + class OBMessageHandler { + // Name; + // Func; + // ArgTypeName; + } + class OBEventHandler { + // Name; + // Func; + } + class OBInstruction { + // Position; + /** + * + * @param {number} code + * @param {OBFunctionBuilder} builder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + init(code, builder, instructions, i) { + + } + /** + * + * @param {OBFunctionBuilder} funcbuilder + * @param {OBInstruction[]} instructions + * @param {number} i + */ + link(funcbuilder, instructions, i) { + + } + } + class OBByteCodes { + static createInstruction(cmd) { + switch (cmd) { + //case 0: + // break; + case 1: + return new PRT(); + case 2: + return new ARITHI(); + case 3: + return new ARITHF(); + case 4: + return new LDSTR(); + case 5: + return new LDI(); + case 6: + return new LDF(); + case 7: + return new RET(); + case 8: + throw Error("Unknown byte code command:" + cmd); + case 9: + throw Error("Unknown byte code command:" + cmd); + case 10: + return new CHSTT(); + case 11: + return new STVG(); + case 12: + return new FSMVS(); + case 13: + return new FSMVG(); + case 14: + return new STVS(); + case 15: + return new MethodCall(); + case 16: + return new MethodCallRegisterInfoAnchor(); + case 17: + return new CreateFSM(); + case 18: + return new FSMSendMsg(); + case 19: + return new ReceivedMessage(); + case 20: + return new GetStructField(); + case 21: + return new SetStructField(); + case 22: + return new GZ0(); + case 23: + return new BRIF(); + case 24: + return new DEC(); + case 25: + return new BR(); + case 26: + return new Reg2Var(); + case 27: + return new Var2Reg(); + case 28: + return new NOP(); + case 29: + return new BRIFN(); + case 30: + return new I2F(); + case 31: + return new StructFieldDesc(); + case 32: + return new EQ(); + case 33: + return new NEQ(); + case 34: + return new LT(); + case 35: + return new LTE(); + case 36: + return new GT(); + case 37: + return new GTE(); + case 38: + return new SLF(); + case 39: + return new NativeMethodCall(); + case 40: + return new DestroyFSM(); + case 41: + return new FSMBroadcastMsg(); + case 42: + return new SGLF(); + case 43: + return new RAND(); + case 44: + return new F2I(); + case 45: + return new FSMSendMsgWait_Data(); + case 46: + return new FSMSendMsgWait(); + case 47: + return new FSMBroadcastMsgWait(); + case 48: + return new TextJoin(); + case 49: + return new ToString(); + case 50: + return new Sender(); + case 51: + return new VOM(); + case 52: + return new SHL(); + case 53: + return new AND(); + case 54: + return new FIX(); + case 55: + return new LAND(); + case 56: + return new LOR(); + case 57: + return new LNOT(); + case 58: + return new COND(); + case 59: + return new NEW(); + default: + throw Error("Unknown byte code command:" + cmd); + } + // return new OBInstruction(cmd); + } + } + class PositionUpdatePair { + // targetOffset; + // callback; + } + class OBFunctionBuilder { + // loader; //OBScriptLoader + // StatementLength; //integer + // BuildingFunc; //OBFunction + // PositionUpdatePairList; + // currentInstructPosition; //integer + // RootStatementContext = new OBStatementContext(); //[StatementContext] + + // /** + // * @callback LongRegister + // * @param {OBVMState} + // * @param {OBFunctionBuilder} + // * @param {OBInstruction[]} + // * @returns {number} + // */ + // /** + // * @type LongRegister[] + // */ + // LongRegister; + // /** + // * @callback DoubleRegister + // * @param {OBVMState} + // * @param {OBFunctionBuilder} + // * @param {OBInstruction[]} + // * @returns {number} + // */ + // /** + // * @type DoubleRegister[] + // */ + // DoubleRegister; + // /** + // * @callback StringRegister + // * @param {OBVMState} + // * @param {OBFunctionBuilder} + // * @param {OBInstruction[]} + // * @returns {string} + // */ + // /** + // * @type StringRegister[] + // */ + // StringRegister; + // /*@ + // * @callback StringRegister + // * @param {OBVMState} + // * @param {OBFunctionBuilder} + // * @param {OBInstruction[]} + // * @returns {OBStructValue} + // */ + // /** + // * @type {Array} StructRegister[] + // */ + // StructRegister; + // /*@ + // * @callback StringRegister + // * @param {OBVMState} + // * @param {OBFunctionBuilder} + // * @param {OBInstruction[]} + // * @returns {object} + // */ + // /** + // * @type {Array} NObjectRegister[] + // */ + // NObjectRegister; + + constructor(loader) { + this.loader = loader; + this.RootStatementContext = new OBStatementContext(); //[StatementContext] + } + + loadFunctionHeader(reader) { + let data = this.loader.data; + let BuildingFunc = new OBFunction(); + this.BuildingFunc = BuildingFunc; + + let header = reader.ReadUInt32(); + let pos = reader.pos; + // this.StatementLength = header * 4 - pos; + reader.pos = header * 4; + let nameIdx = reader.ReadUInt32(); + BuildingFunc.Signure = data.GetString(nameIdx); + this.LongRegister = []; + this.LongRegister.length = reader.ReadUInt32(); + this.DoubleRegister = []; + this.DoubleRegister.length = reader.ReadUInt32(); + this.StringRegister = []; + this.StringRegister.length = reader.ReadUInt32(); + this.StructRegister = []; + this.StructRegister.length = reader.ReadUInt32(); + this.NObjectRegister = []; + this.NObjectRegister.length = reader.ReadUInt32(); + let varInfo = []; + for (let i = 0; i < 5; i++) { + let info = new OBVariableInfo(); + info.typeIdx = i; + info.count = reader.ReadUInt32(); + varInfo[i] = info; + } + this.StatementLength = reader.ReadUInt32(); + BuildingFunc.Variables = varInfo; + reader.pos = pos; + } + + loadStatement(reader) { + let length = this.StatementLength; + this.BuildingFunc.instructions = []; + this.PositionUpdatePairList = []; //[PositionUpdatePair] + for (let i = 0; i < length; i++) { + let instPos = reader.pos; + let code = reader.ReadUInt32(); + let cmd = (code >> 24); + let inst = OBByteCodes.createInstruction(cmd); + inst.Position = instPos; + inst.init(code, this, this.BuildingFunc.instructions, i); + this.BuildingFunc.instructions[i] = inst; + } + } + + link() { + let instructions = this.BuildingFunc.instructions; + for (let i = 0; i < instructions.length; i++) { + let inst = instructions[i]; + this.currentInstructPosition = inst.Position; + inst.link(this, instructions, i); + } + this.PositionUpdatePairList = null; + this.BuildingFunc.Statements = this.RootStatementContext; + } + + build() { + return this.BuildingFunc; + } + + PositionUpdate(targetOffset, callback) { + if (this.PositionUpdatePairList == null) { + throw Error("异常状态"); + } + let p = new PositionUpdatePair(); + p.targetOffset = targetOffset; + p.callback = callback; + this.PositionUpdatePairList.push(p); + } + + PushAction(Instruction) { + let stmt = this.RootStatementContext; + let newPos = stmt.Actions.length; + stmt.PushAction(Instruction); + this.PositionUpdatePairList.forEach((p) => { + if (p.targetOffset === this.currentInstructPosition) { + p.callback(newPos); + } + }); + } + } + + class OBBuildInFunctions { + /** + * + * @param {OBScript} script + */ + static install(script) { + script.InstallLib("", "", [ + OBBuildInFunctions.FSM_FindFsmByTypeInstaller, + OBBuildInFunctions.FSM_FindFsmByNameInstaller, + OBBuildInFunctions.Structs_LoadStructFromDatasetInstaller, + // OBBuildInFunctions.FSM_TargetInstaller, + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Length, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IsEmpty, 'LongRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_IndexOf, 'LongRegister', ['StringRegister', 'StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_CharAt, 'StringRegister', ['StringRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_GetSubstring, 'StringRegister', ['StringRegister', 'LongRegister', 'LongRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToUpperCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToLowerCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_ToTitleCase, 'StringRegister', ['StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Count, 'LongRegister', ['StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Replace, 'StringRegister', ['StringRegister', 'StringRegister', 'StringRegister']), + script.NativeUtil.closureReturnValue(OBBuildInFunctions.Text_Reverse, 'StringRegister', ['StringRegister']), + ]); + } + /** + * + * @param {String} str + * @returns + */ + static Text_Reverse(str) { + if (str) { + return str.split('').reverse().join(''); + } else { + return ""; + } + } + static Text_Replace(haystack, needle, replacement) { + needle = needle.replace(/([-()\[\]{}+?*.$\^|,:# end) { + let t = start; + start = end; + end = t; + } + return str.substring(start, end + 1); + } + static Text_CharAt(str, index) { + if (index === 0) { + return ""; + } + if (index > 0) { + return str[index - 1] || ""; + } + if (index < 0) { + return str[str.length + index]; + } + } + static Text_IndexOf(str, sub, forward) { + if (forward === 1) { + return str.indexOf(sub) + 1; + } else { + return str.lastIndexOf(sub) + 1; + } + } + static Text_IsEmpty(str) { + return str.length === 0 ? 1 : 0; + } + static Text_Length(str) { + return str.length; + } + static FSM_FindFsmByTypeInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let argIdx = args[1] & 0xFFF; + let a1 = builder.StringRegister[argIdx]; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + let r = state.fsm.VM.FindRunningFSMByType(a1(state, func, locals)); + return r; + }; + } + static FSM_FindFsmByNameInstaller() { + } + static Structs_LoadStructFromDatasetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + let idIdx = args[2] & 0xFFF; + let a1 = builder.LongRegister[idIdx]; + let typeIdx = args[1] & 0xFFF; + let a2 = builder.StringRegister[typeIdx]; + let StructData = builder.loader.script.StructData; + builder.StructRegister[returnRegisterIdx] = (state, func, locals) => { + let typename = a2(state, func, locals); + let id = a1(state, func, locals); + let r = StructData.Get(typename, id); + if (!r) { + throw `Can't find ${typename} which id is ${id}`; + } + return r; + }; + } + static FSM_TargetInstaller(builder, args) { + let returnRegisterIdx = args[0] & 0xFFF; + builder.NObjectRegister[returnRegisterIdx] = (state, func, locals) => { + return state.fsm.Target; + }; + } + } + class OBStructValue { + // /** + // * @type {OBStructDef} + // */ + // Def; + // /** + // * @type {OBTypedVariableGroup} + // */ + // registers; + + constructor(Def) { + this.Def = Def; + let registers = new OBTypedVariableGroup(null); + registers.LongRegister = []; + registers.LongRegister.fill(0, 0, Def.IntegerCnt); + registers.DoubleRegister = []; + registers.DoubleRegister.fill(0, 0, Def.FloatCnt); + registers.StringRegister = []; + registers.StringRegister.fill('', 0, Def.StringCnt); + registers.StructRegister = []; + registers.StructRegister.length = Def.StructCnt; + registers.NObjectRegister = []; + registers.NObjectRegister.length = Def.NobjectCnt; + this.registers = registers; + } + + toString() { + return "Struct." + this.Def.Name; + } + } + class StructData { + // /** + // * @type {Object.} + // */ + // StructDef; + // /** + // * @type {Object.} + // */ + // Groups; + // /** + // * @type {OBArrayBufferReader} + // */ + // DataSegment; + + constructor(structDataGroups, data) { + this.Groups = structDataGroups; + this.DataSegment = data; + } + /** + * + * @param {string} type fullname of type + * @1param {integer} id id of data + * @param {?Object.} + * @returns {OBStructValue} + */ + Get(type, id, loading) { + if (type.startsWith("S") && type.endsWith(";")) { + type = type.substr(1, type.length - 2); + } + if (loading == null) { + loading = {}; + } else { + let loaded = loading[id + "@" + type]; + if (loaded) { + return loaded; + } + } + let def = this.StructDef[type]; + let group = this.Groups[type]; + if (!group) { + throw `There is no preset data of the type ${type}`; + } + let reader = group.Data; + let itemStart = 0; + for (let i = 0; i < group.StructCount; i++) { + reader.pos = itemStart; + let length = reader.ReadInt32(); + let itemid = reader.ReadUInt32(); + if (itemid === id) { + reader.pos -= 4; + let s = new OBStructValue(def); + loading[id + "@" + type] = s; + for (let j = 0; j < def.IntegerCnt; j++) { + s.registers.LongRegister[j] = reader.ReadInt32(); //VariableValueSet(j, reader.ReadInt32()); + } + for (let j = 0; j < def.StringCnt; j++) { + let idx = reader.ReadUInt32(); + let str = this.DataSegment.GetString(idx); + s.registers.StringRegister[j] = str; //VariableValueSet(j, str); + } + for (let j = 0; j < def.FloatCnt; j++) { + s.registers.DoubleRegister[j] = reader.ReadSingle(); //VariableValueSet(j, reader.ReadSingle()); + } + for (let j = 0; j < def.StructCnt; j++) { + let fieldDef = def.StructFields[j]; + if (fieldDef.startsWith("S")) { + let subId = reader.ReadUInt32(); + let subStruct = this.Get(def.StructFields[j], subId, loading); + s.registers.StructRegister[j] = subStruct; //VariableValueSet(j, subStruct); + } else if (fieldDef.startsWith("I")) { + // TODO + } else if (fieldDef.startsWith("N")) { + let elementTypeName = fieldDef.substr(1); + let structCnt = reader.ReadUInt32(); + let map = {}; + for (let k = 0; k < structCnt; k++) { + let keyIdx = reader.ReadUInt32(); + let keyStr = this.DataSegment.GetString(keyIdx); + let structId = reader.ReadInt32(); + let st = this.Get(elementTypeName, structId, loading); + map[keyStr] = st; + } + s.registers.StructRegister[j] = map; + } + } + return s; + } else { + itemStart += length * 4 + 4; + } + } + throw Error("找不到 ID为" + id + "的" + type); + } + } + + class OBStructDataReader { + /** + * + * @param {OBArrayBufferReader} reader + * @returns {StructData} + */ + readStream(reader) { + let dataLength = reader.ReadUInt32(); + let data = reader.readSub(dataLength); + return this.readStructData(reader, data); + } + /** + * + * @param {OBArrayBufferReader} reader + * @param {OBArrayBufferReader} data + * @returns {StructData} + */ + readStructData(reader, data) { + let _length = reader.ReadInt32(); + let structs = {}; + + let groupCnt = reader.ReadUInt32(); + for (let i = 0; i < groupCnt; i++) { + let offset = reader.pos; + let strIdx = reader.ReadUInt32(); + let FullName = data.GetString(strIdx); + let structCnt = reader.ReadInt32(); + let length = reader.ReadInt32(); + // arraybuffer + let bin = reader.readSub(length * 4); + let info = new OBStructValueData(); // + info.Data = bin; + info.FullName = FullName; + info.Offset = offset; + info.Length = length; + info.StructCount = structCnt; + structs[FullName] = info; + } + return new StructData(structs, data); + } + } + class Relocation { + constructor() { + /** + * @1type {Object.:{idx:Number,inited:bool}>} + */ + this.string = {}; + /** + * @1type {Object.} + */ + this.integer = {}; + /** + * @1type {Object.} + */ + this.float = {}; + /** + * @1type {Object.} + */ + this.bin = {}; + /** + * @1type {Object.} + */ + this.structFieldIndex = {}; + } + + addRelocationString(str) { + if ((typeof str) !== 'string') { + throw Error('不是字符串'); + } + if (!this.string.hasOwnProperty(str)) { + this.string[str] = { + idx: 0, + inited: false + } + } + } + } + class OBScriptLoader { + constructor() { + // /** + // * @type {OBArrayBufferReader} + // */ + // reader; //OBArrayBufferReader + // /** + // * @type {OBArrayBufferReader} + // */ + // data; //OBArrayBufferReader + this.loadingFunctions = {}; //[OBFunctionBuilder] + this.Linkings = []; //Linkable + } + /** + * @callback NativeLibInstaller + * @param {OBScript} script + */ + /** + * + * @param {ArrayBuffer} arraybuffer of byte code + * @param {NativeLibInstaller} nativeLibs + * @returns + */ + static loadScript(arraybuffer, nativeLibs) { + let script = new OBScript(); + OBBuildInFunctions.install(script); + let l = new OBScriptLoader(); + // let nativeLibs = OBNative.functions; + if (nativeLibs) { + if (Array.isArray(nativeLibs)) { + nativeLibs.forEach(installer => { + installer(script); + }); + } else { + nativeLibs(script); + } + } + l.load(script, arraybuffer); + return script; + } + load(script, buf) { + this.script = script; + this.reader = new OBArrayBufferReader(buf); + this.readXE(); + } + + readXE() { + let MAG = this.reader.ReadInt32(); //'\u007fUEX'; + if (MAG != 0x5845557F) { + throw Error("Unknown MAG:" + MAG); + } + let version = this.reader.ReadUInt32(); + if (version != 1) { + throw Error("Unsupported version." + version); + } + + let SegmentCnt = this.reader.ReadUInt32(); + let headerEnd = this.reader.pos + SegmentCnt * 2 * 4; + + let codes = []; + + for (let i = 0; i < SegmentCnt; i++) { + let type = this.reader.ReadUInt32(); + let startIn4Bytes = this.reader.ReadUInt32(); + let start = headerEnd + startIn4Bytes * 4; + let pos = this.reader.pos; + switch (type) { + case 0: + this.reader.seek(start); + this.data = this.loadDataSegment(); + break; + case 1: + this.reader.seek(start); + let code = this.loadCodeSegment(); // data应该是第一个段,所以此时data已经存在 + codes.push(code); + break; + case 2: + this.reader.seek(start); + this.script.StructData = this.loadStructDataSegment(); + this.script.StructData.StructDef = this.script.StructDef; + break; + case 3: + this.reader.seek(start); + this.script.StructDef = this.loadStructDefDataSegment(); + break; + case 4: + this.reader.seek(start); + this.loadPackageInfo(); + break; + default: + throw Error("Unknown Segment type:" + type); + } + this.reader.seek(pos); + } + this.script.loadedFunctions = this.loadingFunctions; + this.Linkings.forEach(l => { + l.link(); + }); + codes.forEach(codeSeg => { + codeSeg.fsms.forEach(fsm => { + fsm.FullName = codeSeg.name + "." + fsm.Name; + this.script.FullNameFSMData[fsm.FullName] = fsm; + }); + }); + } + + loadCodeSegment() { + let reader = this.reader; + let data = this.data; + + let start = reader.pos; + let SegmentReader = reader.getSub(start); + let length = SegmentReader.ReadUInt32(); + let header = SegmentReader.ReadUInt32() * 4; + SegmentReader.pos = header; + let segment = new OBCodeSegment(); + let nameStringIdx = SegmentReader.ReadInt32(); + let name = data.GetString(nameStringIdx); + let ufunctions = this.readFunctions(SegmentReader); + let fsms = this.readFSMs(SegmentReader, name); + // 字段赋值 + segment.name = name; + segment.functions = ufunctions; + segment.fsms = fsms; + return segment; + } + + readFSMs(reader, moduleName) { + let cnt = reader.ReadInt32(); + let f = []; // [OBFSM] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = s; + let fsm = this.readFSM(reader); + fsm.ModuleName = moduleName; + fsm.FullName = moduleName + "." + fsm.Name; + reader.pos = pos; + f[i] = fsm; + } + return f; + } + + readFSM(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + let fucCnt = reader.ReadUInt32(); + // TODO + let states = this.readStates(reader); + let entryStateNameIdx = reader.ReadUInt32(); + let entryStateName = data.GetString(entryStateNameIdx); + let entryState = null; + + // Dictionary stateDict = new Dictionary(); + let stateDict = {}; + for (let i = 0; i < states.length; i++) { + let s = states[i]; + stateDict[s.Name] = s; + if (entryStateName === s.Name) { + entryState = s; + } + } + if (entryState == null) { + throw Error("Can't find state named " + entryStateName + " FSM " + name); + } + let fsm = new OBFSM(); + fsm.Name = name; + fsm.States = stateDict; + fsm.Entry = entryState; + fsm.Variables = variables; + return fsm; + } + + readStates(reader) { + let cnt = reader.ReadInt32(); + let r = []; //[OBState] + for (let i = 0; i < cnt; i++) { + let s = reader.ReadUInt32() * 4; + let p = reader.pos; + reader.pos = s; + r.push(this.readState(reader)); + reader.pos = p; + } + return r; + } + + readState(reader) { + let data = this.data; + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let variables = this.readVariables(reader); + // 读取函数 + this.readFunctions(reader); + // UMessageHandler[] + let handlers = this.readHandlers(reader); + // UEventHandler[] + let ehandlers = this.readEHandlers(reader); + // Dictionary> Mh = new Dictionary>(); + let Mh = {}; + for (let i = 0; i < handlers.length; i++) { + let h = handlers[i]; + let hl = Mh[h.Name]; + if (hl) { + } else { + hl = []; //new List(); + Mh[h.Name] = hl; + } + hl.push(h); + } + // Dictionary eh = new Dictionary(); + let eh = {}; + for (let i = 0; i < ehandlers.length; i++) { + let h = ehandlers[i]; + eh[h.Name] = h; + } + let r = new OBState(); + r.Variables = variables; + r.Name = name; + r.MessageHandlers = Mh; + r.EventHandlers = eh; + return r; + } + + readEHandlers(reader) { + let cnt = reader.ReadInt32(); + // UEventHandler[] f = new UEventHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readEHandler(reader, start); + f[i] = h; + } + return f; + } + + readEHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBEventHandler(); + h.Name = func.Signure; + h.Func = func; + reader.pos = pos; + return h; + } + + readHandlers(reader) { + let cnt = reader.ReadUInt32(); + // UMessageHandler[] f = new UMessageHandler[cnt]; + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let h = this.readHandler(reader, start); + f[i] = h; + } + return f; + } + + readHandler(reader, start) { + let pos = reader.pos; + reader.pos = start; + let func = this.readFunction(reader); + let h = new OBMessageHandler(); + let pair = func.Signure.split(':'); + h.Name = pair[0]; + h.Func = func; + h.ArgTypeName = pair[1]; + reader.pos = pos; + return h; + } + + readVariables(reader) { + let data = this.data; + let varCnt = reader.ReadUInt32(); + // List d = new List(); + let d = []; + for (let i = 0; i < varCnt; i++) { + let v = this.readVariable(reader); + d.push(v); + } + return d; + } + + readVariable(reader) { + // let typeIdx = reader.ReadUInt32(); + // let count = reader.ReadInt32(); + let vari = reader.ReadUInt32(); + let count = vari & 0xFFFFFFF; + let typeIdx = vari >> 28; + let v = new OBVariableInfo(typeIdx, count); + return v; + } + + readFunctions(reader) { + let cnt = reader.ReadInt32(); + let f = []; + for (let i = 0; i < cnt; i++) { + let start = reader.ReadUInt32() * 4; + let pos = reader.pos; + reader.pos = start; + let _f = this.readFunction(reader); + f[i] = _f; + this.loadingFunctions[_f.Signure] = _f; + reader.pos = pos; + } + return f; + } + + readFunction(reader) { + let builder = new OBFunctionBuilder(this); + builder.loadFunctionHeader(reader); + builder.loadStatement(reader); + this.addLinking(builder); + let f = builder.build(); + return f; + } + + addLinking(l) { + this.Linkings.push(l); + } + + loadStructDataSegment() { + let reader = this.reader; + let data = this.data; + return new OBStructDataReader().readStructData(reader, data); + } + /** + * + * @returns {Object.} + */ + loadStructDefDataSegment() { + let reader = this.reader; + let data = this.data; + let length = reader.ReadUInt32(); + let d = {}; + let cnt = reader.ReadUInt32(); + for (let i = 0; i < cnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let typeCnt = reader.ReadUInt32(); + let structCnt = (typeCnt & 0x7F); + let stringCnt = ((typeCnt >> 7) & 0x7F); + let integerCnt = ((typeCnt >> 14) & 0x7F); + let floatCnt = ((typeCnt >> 21) & 0x7F); + let NobjectCnt = ((typeCnt >> 28)); + // string[] fields = new string[structCnt]; + let fields = []; + for (let j = 0; j < structCnt; j++) { + let fnameIdx = reader.ReadUInt32(); + let fname = data.GetString(fnameIdx); + fields[j] = fname; + } + let s = new OBStructDef(); + s.Name = name; + s.StructCnt = structCnt; + s.StringCnt = stringCnt; + s.IntegerCnt = integerCnt; + s.FloatCnt = floatCnt; + s.NobjectCnt = NobjectCnt; + s.StructFields = fields; + d[name] = s; + } + return d; + } + + loadDataSegment() { + let length = this.reader.ReadUInt32(); + return this.reader.readSub(length * 4); + } + + loadPackageInfo() { + let reader = this.reader; + let data = this.data; + let depCnt = reader.ReadUInt32(); + let err = []; + for (let i = 0; i < depCnt; i++) { + let nameIdx = reader.ReadUInt32(); + let name = data.GetString(nameIdx); + let hashIdx = reader.ReadUInt32(); + let hash = data.GetString(hashIdx); + let lhash = this.script.NativeLibHash[name]; + if (!lhash) { + err.push("No native lib named " + name); + } else if (lhash != hash) { + err.push("Native lib hash mismatching." + name + " require " + hash + ", provide " + lhash); + } + } + if (err.length > 0) { + // throw err; + console.error(err); + } + } + } + + class OBArrayBufferReader { + // /** + // * @type {Number} integer of position + // */ + // pos; // int + // /** + // * @type {Number} integer of start + // */ + // start; // int + // /** + // * @type {ArrayBuffer} + // */ + // buf; // ArrayBuffer + // /** + // * @type DataView + // */ + // view; // DataView + // /** + // * @type {Object.} + // */ + // stringCache = {}; + + constructor(buf) { + this.buf = buf; + this.pos = 0; + this.start = 0; + this.view = new DataView(buf); + this.stringCache = {}; + } + + ReadInt32() { + let v = this.getInt32(this.pos); + this.pos += 4; + return v; + } + + getInt32(p) { + let v = this.view.getInt32(this.start + p, true); + // let v = this.view.getInt32(p, true); + return v; + } + + ReadUInt32() { + let v = this.getUint32(this.pos); + this.pos += 4; + return v; + } + + getUint32(p) { + let v = this.view.getUint32(this.start + p, true); + // let v = this.view.getUint32(p, true); + return v; + } + + ReadSingle() { + let v = this.getFloat(this.pos); + return v; + } + + getFloat(p) { + let v = this.view.getFloat32(this.start + p, true); + // let v = this.view.getFloat32(p, true); + return v; + } + + GetString(stringIdx) { + let str = this.stringCache[stringIdx]; + if (str) { + return str; + } + let start = stringIdx * 8; // 字符串是8字节对齐 + let length = this.view.getUint32(this.start + start, true); + if (length === 0) { + return ""; + } + start = this.start + start + 4; + // start = start + 4; + let ab = this.buf.slice(start, start + length); + let ui8 = new Uint8Array(ab); + let utf8decoder = new util.TextDecoder("utf-8", { + fatal: true + }); + str = utf8decoder.decode(ui8); + if (str === null) { + throw Error('no string value of idx:' + stringIdx); + } + this.stringCache[stringIdx] = str; + return str; + } + + readSub(length) { + let v = this.getSub(this.pos, length); + this.pos += length; + return v; + } + + getSub(pos, length) { + // let buf; + // if (typeof (length) === "undefined") { + // buf = this.buf.slice(pos); + // } else { + // buf = this.buf.slice(pos, pos + length); + // } + // let reader = new OBArrayBufferReader(buf); + // reader.start = this.start + pos; + // return reader; + let reader = new OBArrayBufferReader(this.buf); + reader.start = this.start + pos; + return reader; + } + + seek(pos) { + if (typeof (pos) === "number") { + this.pos = pos; + } + return this.pos; + } + /** + * + * @param {Number} startIdx + * @returns {number[]} + */ + GetInt32FromBin(startIdx) { + let start = startIdx * 8; // 8字节对齐 + let p = this.pos; + this.pos = start; + let byteLength = this.ReadUInt32(); + let length = byteLength / 4; + let r = []; + for (let i = 0; i < length; i++) { + r.push(this.ReadInt32()); + } + this.pos = p; + return r; + } + } + + + class OBStatementContext { + constructor() { + // this.InstPos; + this.Actions = []; + } + PushAction(Instruction) { + this.Actions.push(Instruction); + } + } + // 虚拟机 + + class VMInterruptException { + } + class ChangeStateException extends VMInterruptException { + } + class ChangeDestroyException extends VMInterruptException { + } + class OBVM { + // /** + // * @1type {function(any)} + // */ + // Output; + // setTimeout; + // /** + // * typeName->[VMFSM] + // * @1type {Object.} + // */ + // Running = {}; + // /** + // * @type OBScript + // */ + // script; + // /** + // * @1type {OBVMFSM} + // */ + // Pending = []; + /** + * + * @param {OBScript} script + */ + constructor(script, config) { + this.Running = {}; + this.Pending = []; + if (!script) { + throw Error("Script is null"); + } + this.script = script; + if (config) { + Object.assign(this, config); + } + if (!this.setTimeout) { + this.setTimeout = setTimeout.bind(window); + } + } + + CreateFSM(name) { + if (name == null) { + return null; + } + if (this.script == null) { + throw Error("Script is null"); + } + let fsmdata = this.script.FullNameFSMData[name]; + if (!fsmdata) { + for(let key in this.script.FullNameFSMData){ + if(key === name){ + return this.script.FullNameFSMData[key]; + } + } + return null; + } + let uBFSM = new OBVMFSM(this, fsmdata); + let list = this.Running[name]; + if (!list) { + list = []; + this.Running[name] = list; + } + list.push(uBFSM); + return uBFSM; + } + + update() { + this._HandleOnePendingFSM(); + // let timestamp = Date.now(); + // JS不需要在VM中处理计划任务 + // this._HandleSchedulingTask(timestamp); + // this._InvokeScheduledTask(timestamp); + } + + _HandleOnePendingFSM() { + while (this.Pending.length > 0) { + let fsm = this.Pending.shift(); + if (fsm) { + fsm.HandleAllMessages(); + } + } + } + /** + * + * @param {OBVMFSM} fsm + */ + _AddPendingFSM(fsm) { + this.Pending.push(fsm); + } + + Log(v) { + console.log(v); + if (this.Output) { + this.Output(v); + } + } + /** + * + * @param {OBVMFSM} fsm + */ + DestroyFSM(fsm) { + let name = fsm.data.FullName; + let list = this.Running[name]; + if (list) { + let idx = list.findIndex((f) => f === fsm); + if (idx > -1) { + list.splice(idx, 1); + } + } + } + /** + * + * @param {OBUserMessage} userMessage + */ + BroadcastMessage(userMessage) { + Object.values(this.Running).forEach(l => { + for (let i = 0; i < l.length; i++) { + let f = l[i]; + if (f && f != userMessage.sender) { + f.PostMessage(userMessage); + } + } + }); + } + /** + * + * @param {number} millisecond wait time + * @param {*} callback + */ + Schedule(millisecond, callback) { + this.setTimeout(callback, millisecond, this); + } + + FindRunningFSMByType(typeFullName) { + return this.Running[typeFullName] || []; + } + } + let ID_GEN = 0; + class OBVMFSM { + // /** + // * @type {any} + // */ + // Target; + // /** + // * @type {OBFSM} + // */ + // data; + // id; + // /** + // * @type {OBVMState} + // */ + // CurrentState; + // /** + // * @type {OBVMState[]} + // */ + // StateStack = []; + // /** + // * @type {OBVM} + // */ + // VM; + // Inbox = []; + // PrioritizedInbox = []; + // VariableGroup; + /** + * + * @param {OBVM} vm + * @param {OBFSM} data + */ + constructor(vm, data) { + this.Running = true; + this.OnDestroyedCallbacks = []; + this.StateStack = []; + this.Inbox = []; + this.PrioritizedInbox = []; + this.data = data; + this.id = ++ID_GEN; + this.VM = vm; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.CurrentState = new OBVMState(data.Entry, this); + this.PostPrioritizedMessage(new OBEventMessage("Start", "", null, null)); + } + /** + * 推送高优先级消息 + * @param {OBMessage} msg + */ + PostPrioritizedMessage(msg) { + if (this.PrioritizedInbox == null) { + return; + } + this.PrioritizedInbox.push(msg); + this.VM._AddPendingFSM(this); + } + /** + * 推送消息 + * @param {OBMessage} msg + */ + PostMessage(msg) { + if (this.Inbox == null) { + return; + } + this.Inbox.push(msg); + this.VM._AddPendingFSM(this); + } + + HandleAllMessages() { + if (!this.CurrentState) { + return; + } + let msg; + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + while (msg = this.Inbox.shift()) { + msg.Handle(this.CurrentState); + while (msg = this.PrioritizedInbox.shift()) { + msg.Handle(this.CurrentState); + } + } + } + + OnDestroyed(f) { + this.OnDestroyedCallbacks.push(f); + } + OffDestroyed(f) { + let idx = this.OnDestroyedCallbacks.indexOf(f); + if (idx >= 0) { + this.OnDestroyedCallbacks.slice(idx, 1); + } + } + Destroy() { + this.VariableGroup = null; + this.CurrentState = null; + this.Inbox.length = 0; + this.StateStack.length = 0; + this.PrioritizedInbox.length = 0; + this.VM.DestroyFSM(this); + this.Running = false; + this.OnDestroyedCallbacks.forEach(f => { + f(this); + }); + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return this.CurrentState.IsListeningEvent(title); + } + + toString() { + return "FSM:" + this.data.FullName; + } + + ChangeState(name) { + + if (this.VM == null) { + return; + } + if (this.data.States[name]) { + this.CurrentState = new OBVMState(this.data.States[name], this); + this.PostPrioritizedMessage(new OBEventMessage("Start", null, null, this)); + } else { + throw Error("No state named " + name + " of FSM " + this.data.Name); + } + } + } + class OBTypedVariableGroup { + // LongRegister; + // DoubleRegister; + // StringRegister; + // StructRegister; + // NObjectRegister; + /** + * + * @param {OBVariableInfo[]} variables + */ + constructor(variables) { + if (!variables) { + return; + } + variables.forEach(v => { + switch (v.typeIdx) { + case 0: + if (this.LongRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.LongRegister = []; + this.LongRegister.length = v.count; + this.LongRegister.fill(0); + break; + case 1: + if (this.DoubleRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.DoubleRegister = []; + this.DoubleRegister.length = v.count; + this.DoubleRegister.fill(0); + break; + case 2: + if (this.StringRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StringRegister = []; + this.StringRegister.length = v.count; + this.StringRegister.fill(""); + break; + + case 3: + if (this.StructRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.StructRegister = []; + this.StructRegister.length = v.count; + break; + case 4: + if (this.NObjectRegister != null) { + throw Error("duplicated type " + v.typeIdx); + } + this.NObjectRegister = []; + this.NObjectRegister.length = v.count; + break; + default: + throw Error("Unknown type " + v.typeIdx); + } + }); + } + } + class OBVMState { + // /** + // * @type {OBState} + // */ + // data; + // /** + // * @type {OBVMFSM} + // */ + // fsm; + // /** + // * @type {OBTypedVariableGroup} + // */ + // VariableGroup; + // /** + // * @type {OBMessage} + // */ + // currentMessage; + + constructor(data, fsm) { + this.data = data; + this.VariableGroup = new OBTypedVariableGroup(data.Variables); + this.fsm = fsm; + } + /** + * + * @param {OBMessage} msg + */ + HandleEvent(msg) { + try { + let h = this.data.EventHandlers[msg.name]; + if (h) { + this.currentMessage = msg; + new OBVMFunction(h.Func).Call(this); + } + } finally { + this.currentMessage = null; + } + } + + HandleMessage(m) { + this.currentMessage = m; + try { + let typeName = null; + if (m.arg != null) { + typeName = m.GetArgType(); + } + let hl = this.data.MessageHandlers[m.name]; + if (hl) { + hl.forEach(h => { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + new OBVMFunction(h.Func).Call(this); + } + }); + } + } finally { + this.currentMessage = null; + } + } + /** + * + * @param {string} title + * @returns bool + */ + IsListeningEvent(title) { + return !!this.data.EventHandlers[title]; + } + + ReceivedMessage() { + if (this.currentMessage) { + return this.currentMessage.arg; + } else { + throw Error("当前上下文没有消息可用"); + } + } + + CurrentMessageSender() { + if (this.currentMessage) { + return this.currentMessage.sender; + } else { + throw Error("当前上下文没有消息可用"); + } + } + } + class OBVMFunction { + // /** + // * @type {OBFunction} + // */ + // data; + // /** + // * @type {OBTypedVariableGroup} + // */ + // LocalVar; + // returnType = -1; + // returnValue; + // LongRegister; + // DoubleRegister; + // StringRegister; + // StructRegister; + // NObjectRegister; + /** + * + * @param {OBFunction} obfunc + */ + constructor(obfunc, builder, args) { + this.returnType = -1; + this.data = obfunc; + let LocalVar = new OBTypedVariableGroup(obfunc.Variables); + this.LocalVar = LocalVar; + if (builder) { + /** + * @1type {List>();} + */ + let LongRegister_ = []; + let DoubleRegister_ = [];// new List>(); + let StringRegister_ = [];// new List>(); + let StructRegister_ = [];// new List>(); + let NObjectRegister_ = [];//new List>(); + + for (let i = 1; i < args.length; i++) { + let arg = args[i]; + let Register = arg & 0xFFF; + let RegisterType = (arg >> 12) & 0xF; + + switch (RegisterType) { + case 0: + LongRegister_.push(builder.LongRegister[Register]); + break; + case 1: + DoubleRegister_.push(builder.DoubleRegister[Register]); + break; + case 2: + StringRegister_.push(builder.StringRegister[Register]); + break; + case 3: + StructRegister_.push(builder.StructRegister[Register]); + break; + case 4: + NObjectRegister_.push(builder.NObjectRegister[Register]); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + if (LongRegister_.length > 0) { + this.LongRegister = LongRegister_; + } + if (DoubleRegister_.length > 0) { + this.DoubleRegister = DoubleRegister_; + } + if (StringRegister_.length > 0) { + this.StringRegister = StringRegister_; + } + if (StructRegister_.length > 0) { + this.StructRegister = StructRegister_; + } + if (NObjectRegister_.length > 0) { + this.NObjectRegister = NObjectRegister_; + } + } + } + /** + * + * @param {OBVMState} state + */ + Call(state, uBFunction, localVars) { + if (uBFunction) { + if (this.LongRegister != null) { + for (let i = 0; i < this.LongRegister.length; i++) { + this.LocalVar.LongRegister[i] = this.LongRegister[i](state, uBFunction, localVars); + } + } + if (this.DoubleRegister != null) { + for (let i = 0; i < this.DoubleRegister.length; i++) { + this.LocalVar.DoubleRegister[i] = this.DoubleRegister[i](state, uBFunction, localVars); + } + } + if (this.StringRegister != null) { + for (let i = 0; i < this.StringRegister.length; i++) { + this.LocalVar.StringRegister[i] = this.StringRegister[i](state, uBFunction, localVars); + } + } + if (this.StructRegister != null) { + for (let i = 0; i < this.StructRegister.length; i++) { + this.LocalVar.StructRegister[i] = this.StructRegister[i](state, uBFunction, localVars); + } + } + if (this.NObjectRegister != null) { + for (let i = 0; i < this.NObjectRegister.length; i++) { + this.LocalVar.NObjectRegister[i] = this.NObjectRegister[i](state, uBFunction, localVars); + } + } + } + let Actions = this.data.Statements.Actions; + for (let i = 0; i < Actions.length && i >= 0;) { + let action = Actions[i]; + i = action(state, this, this.LocalVar, i); + } + } + + SetReturnLong(v) { + this.returnType = 1; + this.returnValue = v; + } + + Long() { + if (this.returnType === 1) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 long 类型:" + this.returnType); + } + } + + SetReturnDouble(v) { + this.returnType = 2; + this.returnValue = v; + } + + Double() { + if (this.returnType === 2) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 double 类型:" + this.returnType); + } + } + + SetReturnString(v) { + this.returnType = 3; + this.returnValue = v; + } + + String() { + if (this.returnType === 3) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 string 类型:" + this.returnType); + } + } + + SetReturnStruct(v) { + this.returnType = 4; + this.returnValue = v; + } + + Struct() { + if (this.returnType === 4) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 Struct 类型:" + this.returnType); + } + } + + SetReturnNObject(v) { + this.returnType = 5; + this.returnValue = v; + } + + NObject() { + if (this.returnType === 5) { + return this.returnValue; + } + else { + throw Error(this.data.Signure + " 没有返回 NObject 类型:" + this.returnType); + } + } + } + class OBMessage { + // name; + // arg; + // argType; + // sender; + /** + * + * @param {string} name + * @param {string} argType + * @param {any} arg + * @param {?OBVMFSM} sender + */ + constructor(name, argType, arg, sender) { + this.name = name; + this.argType = argType; + this.arg = arg; + this.sender = sender; + } + + GetArgType() { + return this.argType; + } + + static ArgTypeOf(typeId, arg) { + switch (typeId) { + case 0xf: + return ""; + case 0: + return "Integer"; + case 1: + return "Number"; + case 2: + return "String"; + case 3: + return arg.Def.Name; + case 4: + // return "NObject"; + if (arg.constructor === OBVMFSM) { + return "FSM"; + } else { + if (arg.constructor) { + return arg.constructor.name; + } else { + return typeof (arg); + } + } + default: + throw Error("Unknown type:" + typeId); + } + } + } + class OBEventMessage extends OBMessage { + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleEvent(this); + } + catch (err) { + if (!(err instanceof VMInterruptException)) { + state.fsm.VM.Output(err); + state.fsm.VM.Output(err.stack); + console.error(err); + throw err; + } + } + } + } + class OBUserMessage extends OBMessage { + + /** + * + * @param {OBVMState} state + */ + Handle(state) { + try { + state.HandleMessage(this); + } catch (err) { + if (!(err instanceof VMInterruptException)) { + state.fsm.VM.Output(err); + state.fsm.VM.Output(err.stack); + console.error(err); + throw err; + } + } + } + } + // 字节码 + class LDSTR extends OBInstruction { + // Value; + // Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Value = builder.loader.data.GetString(stridx); + this.Register = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.StringRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + return this.Value; + } + } + class PRT extends OBInstruction { + // RegisterType; + // RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = (code & 0xF00000) >> 20; + this.RegisterIdx = code & 0xFFFFF; + } + + link(builder, instructions, idx) { + let v; + switch (this.RegisterType) { + case 0: + v = builder.LongRegister[this.RegisterIdx]; + break; + case 1: + v = builder.DoubleRegister[this.RegisterIdx]; + break; + case 2: + v = builder.StringRegister[this.RegisterIdx]; + break; + case 3: + v = builder.StructRegister[this.RegisterIdx]; + break; + case 4: + v = builder.NObjectRegister[this.RegisterIdx]; + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let val = v(st, uf, locals); + let vm = st.fsm.VM; + vm.Log(val); + return ++pos; + }); + } + } + class ReceivedMessage extends OBInstruction { + // typeId; + // Register; + + init(code, builder, instructions, i) { + this.typeId = (code >> 20) & 0xf; + this.Register = code & 0xfffff; + } + + link(builder, instructions, idx) { + let Register = this.Register; + switch (this.typeId) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.ReceivedMessage(); + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + } + } + class STVS extends OBInstruction { + // Register; + // VarIdx; + // RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + let stt = fst(st, uf, locals); + st.VariableGroup.StructRegister[VarIdx] = stt; + if (!stt) { + debugger + } + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + class STVG extends OBInstruction { + // Register; + // VarIdx; + // RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return st.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + class StructFieldDesc extends OBInstruction { + // fieldTypeId; + // fieldDescIdx; + + init(code, builder, instructions, i) { + this.fieldDescIdx = code & 0xfffff; + this.fieldTypeId = (code >> 20) & 0xf; + } + } + class GetStructField extends OBInstruction { + // structIdx; + // Register; + // typeId; + // fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + + case 0: + builder.LongRegister[Register] = (st, uf, locals) => { + let stt = getStruct(st, uf, locals); + return stt.registers.LongRegister[fieldIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StringRegister[fieldIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.StructRegister[fieldIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, locals) => { + return getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx]; + }; + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + class SetStructField extends OBInstruction { + // structIdx; + // Register; + // typeId; + // fieldIdx; + + init(code, builder, instructions, i) { + let desc = instructions[i - 1]; + if (!(desc instanceof StructFieldDesc)) { + throw Error("last cmd is not StructFieldDesc"); + } + this.structIdx = (code >> 12) & 0xfff; + this.Register = (code) & 0xfff; + this.typeId = desc.fieldTypeId; + this.fieldIdx = desc.fieldDescIdx; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let fieldIdx = this.fieldIdx; + let getStruct = builder.StructRegister[this.structIdx]; + switch (this.typeId) { + case 0: + let getLong = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.LongRegister[fieldIdx] = getLong(st, uf, locals); + return ++pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.DoubleRegister[fieldIdx] = getDouble(st, uf, locals); + return ++pos; + }); + break; + case 2: + let GetString = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StringRegister[fieldIdx] = GetString(st, uf, locals); + return ++pos; + }); + break; + case 3: + let getStruct1 = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.StructRegister[fieldIdx] = getStruct1(st, uf, locals); + return ++pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + getStruct(st, uf, locals).registers.NObjectRegister[fieldIdx] = getNObject(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + this.typeId); + } + + } + } + class CHSTT extends OBInstruction { + // StateName; + + init(code, builder, instructions, i) { + let strIdx = (code & 0xFFFFFF); + let str = builder.loader.data.GetString(strIdx); + this.StateName = str; + } + + link(builder, instructions, idx) { + builder.PushAction((state, uf, locals, pos) => { + state.fsm.ChangeState(this.StateName); + throw new ChangeStateException(); + //return ++pos; + }); + } + } + class MethodCallRegisterInfoAnchor extends OBInstruction { + // RegisterInfoIdx; + + init(code, builder, instructions, i) { + this.RegisterInfoIdx = code & 0xFFFF; + } + } + class NativeMethodCall extends OBInstruction { + // LibNameIdx; + + init(code, builder, instructions, i) { + this.LibNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let LibName = builder.loader.data.GetString(this.LibNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + let funcIdx = args[0]; + let _args = args.slice(1); + let installer = builder.loader.script.getNativeFunc(LibName, funcIdx); + installer(builder, _args); + } + } + class FSMVS extends OBInstruction { + // Register; + // VarIdx; + // RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let Register = this.Register; + let VarIdx = this.VarIdx; + let RegisterType = this.RegisterType; + switch (RegisterType) { + case 0: + let fl = builder.LongRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.LongRegister[VarIdx] = fl(st, uf, locals); + return ++pos; + }); + break; + case 1: + let fd = builder.DoubleRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.DoubleRegister[VarIdx] = fd(st, uf, locals); + return ++pos; + }); + break; + case 2: + let fs = builder.StringRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StringRegister[VarIdx] = fs(st, uf, locals); + return ++pos; + }); + break; + case 3: + let fst = builder.StructRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.StructRegister[VarIdx] = fst(st, uf, locals); + return ++pos; + }); + break; + case 4: + let fo = builder.NObjectRegister[Register]; + builder.PushAction((st, uf, locals, pos) => { + st.fsm.VariableGroup.NObjectRegister[VarIdx] = fo(st, uf, locals); + return ++pos; + }); + break; + default: + throw Error("Unknown type " + RegisterType); + } + } + } + class SLF extends OBInstruction { + // RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterIdx = code & 0xffffff; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RegisterIdx] = (s, f, l) => { + return s.fsm; + }; + } + } + class MethodCall extends OBInstruction { + // MethodNameIdx; + + init(code, builder, instructions, i) { + this.MethodNameIdx = code & 0xFFFFFF; + } + + link(builder, instructions, idx) { + let MethodName = builder.loader.data.GetString(this.MethodNameIdx); + let anchor = instructions[idx - 1]; + if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { + throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + } + let RegisterInfoIdx = anchor.RegisterInfoIdx; + let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); + + let uf1 = builder.loader.script.loadedFunctions[MethodName]; + if (uf1 != null) { + // 参数 + let f = new OBVMFunction(uf1, builder, args); + let returnRegister = args[0]; + if (returnRegister === -1) { + builder.PushAction((state, uf, localVars, pos) => { + f.Call(state, f, localVars); + return ++pos; + }); + } else { + let Register = returnRegister & 0xFFF; + let registerType = (returnRegister >> 12) & 0xF; + // 处理有返回值的情况 + switch (registerType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Long(); + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Double(); + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.String(); + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.Struct(); + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + f.Call(st, uf, l); + return f.NObject(); + }; + break; + default: + throw Error("Unknown type " + registerType); + } + } + } else { + throw Error("未找到函数 " + MethodName); + } + } + } + class BRIFN extends OBInstruction { + // checkRegType; + // checkRegIdx; + // targetOffset; + // targetOffsetBak; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff);//(((code & 0x1fff) << 19) >> 19); //;// ((code) & 0x1fff); + this.targetOffsetBak = this.targetOffset; + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) === 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str == null || ("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) == null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + checkRegType); + } + } + } + class BR extends OBInstruction { + // Offset; + + init(code, builder, instructions, i) { + this.Offset = ((code << 8) >> 8); + builder.PositionUpdate(this.Offset * 4, (newPos) => { + this.Offset = newPos; + }); + } + + link(builder, instructions, idx) { + builder.PushAction((ub, uf, locals, pos) => { + return this.Offset; + }); + } + } + class NOP extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + return pos + 1; + }); + } + } + class ARITHF extends OBInstruction { + // Opcode; + // LeftRegister; + // RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.DoubleRegister[this.LeftRegister]; + let right = builder.DoubleRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l / r; + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.pow(l, r); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.DoubleRegister[this.LeftRegister] = o; + } + } + + class ARITHI extends OBInstruction { + // Opcode; + // LeftRegister; + // RightRegister; + + init(code, builder, instructions, i) { + this.LeftRegister = (code >> 10) & 0x3FF; + this.RightRegister = (code & 0x3FF); + this.Opcode = (code >> 20) & 0xf; + } + + link(builder, instructions, idx) { + let left = builder.LongRegister[this.LeftRegister]; + let right = builder.LongRegister[this.RightRegister]; + if (left == null) { + throw Error("left is null"); + } + if (right == null) { + throw Error("right is null"); + } + let o; + switch (this.Opcode) { + case 0: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l + r; + } + break; + case 1: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l - r; + } + break; + case 2: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l * r; + } + break; + case 3: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(l / r); + } + break; + case 4: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return Math.floor(Math.pow(l, r)); + } + break; + case 5: + o = (st, f, locals) => { + var l = left(st, f, locals); + var r = right(st, f, locals); + return l % r; + } + break; + default: + throw Error("未知操作符 " + this.Opcode); + } + builder.LongRegister[this.LeftRegister] = o; + } + } + class LDI extends OBInstruction { + // Register; + // Value; + + init(code, builder, instructions, i) { + let pos = code & 0xFFF; + this.Value = builder.loader.data.getInt32(pos * 4); // 4字节对齐 + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.LongRegister[this.Register] = () => { + return this.Value; + }; + } + } + class LDF extends OBInstruction { + // Register; + // Value; + + init(code, builder, instructions, i) { + let specal = code & 0xFFFF; + switch (specal) { + case 0xFFFE: + this.Value = Number.POSITIVE_INFINITY; + break; + case 0xFFFD: + this.Value = Number.NEGATIVE_INFINITY; + break; + case 0xFFFF: + this.Value = Number.NaN; + break; + default: + this.Value = builder.loader.data.getFloat(specal * 4); + break; + } + this.Register = ((code & 0xFF0000) >> 16); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = () => { + return this.Value; + }; + } + } + class RET extends OBInstruction { + // RegisterType; + // RegisterIdx; + + init(code, builder, instructions, i) { + this.RegisterType = ((code & 0xF00000) >> 20); + this.RegisterIdx = (code & 0xFFFFF); + } + + link(builder, instructions, idx) { + switch (this.RegisterType) { + case 0: + let l = builder.LongRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = l(st, uf, locals); + uf.SetReturnLong(v); + return -1; + }); + break; + case 1: + let f = builder.DoubleRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + let v = f(st, uf, locals); + uf.SetReturnDouble(v); + return -1; + }); + break; + case 2: + let s = builder.StringRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(s(st, uf)); + let v = s(st, uf, locals); + uf.SetReturnString(v); + return -1; + }); + break; + case 3: + let u = builder.StructRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(u(st, uf)); + let v = u(st, uf, locals); + uf.SetReturnStruct(v); + return -1; + }); + break; + case 4: + let n = builder.NObjectRegister[this.RegisterIdx]; + builder.PushAction((st, uf, locals, pos) => { + //Console.WriteLine(n(st, uf)); + let v = n(st, uf, locals); + uf.SetReturnNObject(v); + return -1; + }); + break; + case 0xf: + builder.PushAction((st, uf, locals, pos) => { + return -1; + }); + break; + default: + throw Error("Unknown type:" + this.RegisterType); + } + } + } + class FSMVG extends OBInstruction { + // Register; + // VarIdx; + // RegisterType; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFF00) >> 8; + this.RegisterType = (code & 0xFF0000) >> 16; + this.VarIdx = code & 0xFF; + } + + link(builder, instructions, idx) { + let VarIdx = this.VarIdx; + let Register = this.Register; + switch (this.RegisterType) { + case 0: + builder.LongRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.LongRegister[VarIdx]; + }; + break; + case 1: + builder.DoubleRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.DoubleRegister[VarIdx]; + }; + break; + case 2: + builder.StringRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StringRegister[VarIdx]; + }; + break; + case 3: + builder.StructRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.StructRegister[VarIdx]; + }; + break; + case 4: + builder.NObjectRegister[Register] = (st, uf, l) => { + return st.fsm.VariableGroup.NObjectRegister[VarIdx]; + }; + break; + default: + throw Error("Unknown type " + this.RegisterType); + } + } + } + class CreateFSM extends OBInstruction { + // FSMTypeName; + // ReturnRegister; + + init(code, builder, instructions, i) { + let FSMTypeNameIdx = code & 0xFFFF; + this.FSMTypeName = builder.loader.data.GetString(FSMTypeNameIdx); + this.ReturnRegister = (code & 0xFF0000) >> 16; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.ReturnRegister] = (st, fun, l) => { + let fsm = st.fsm.VM.CreateFSM(this.FSMTypeName); + if (!fsm) { + st.fsm.VM.Log("未找到FSM类型 " + this.FSMTypeName); + } else { + fsm.Target = st.fsm.Target; + } + return fsm; + }; + } + } + class FSMSendMsg extends OBInstruction { + // TitleIdx; + // TargetIdx; + // BodyTypeID; + // BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let f_fsm = builder.NObjectRegister[this.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let fsm = f_fsm(st, uf, locals); + if (fsm) { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + } + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + let BodyRegisterIdx = this.BodyRegisterIdx; + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + class GZ0 extends OBInstruction { + // VarType; + // VarIdx; + // ResultIdx; + + init(code, builder, instructions, i) { + this.VarType = ((code >> 20) & 0xf); + this.VarIdx = ((code >> 10) & 0x3ff); + this.ResultIdx = (code & 0x3ff); + } + + link(builder, instructions, idx) { + let ResultIdx = this.ResultIdx; + let VarIdx = this.VarIdx; + switch (this.VarType) { + case 0: + let getLong = builder.LongRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + let lv = getLong(st, uf, locals); + return lv > 0 ? 1 : 0; + }; + break; + case 1: + let getDouble = builder.DoubleRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getDouble(st, uf, locals) > 0 ? 1 : 0; + }; + break; + case 2: + let GetString = builder.StringRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return GetString(st, uf, locals) != null ? 1 : 0; + }; + break; + case 3: + let getStruct = builder.StructRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getStruct(st, uf, locals) != null ? 1 : 0; + }; + break; + case 4: + let getNObject = builder.NObjectRegister[VarIdx]; + builder.LongRegister[ResultIdx] = (st, uf, locals) => { + return getNObject(st, uf, locals) == null ? 1 : 0; + }; + break; + default: + throw Error("Unknown type " + this.VarType); + } + } + } + + class BRIF extends OBInstruction { + // checkRegType; + // checkRegIdx; + // targetOffset; + + init(code, builder, instructions, i) { + this.checkRegType = ((code >> 20) & 0xf); + this.checkRegIdx = ((code >> 14) & 0x7f); + this.targetOffset = ((code) & 0x1fff); //;// ((code) & 0x1fff); + builder.PositionUpdate(this.targetOffset * 4, (newPos) => { + this.targetOffset = newPos; + }); + } + + link(builder, instructions, idx) { + let checkRegType = this.checkRegType; + let checkRegIdx = this.checkRegIdx; + switch (checkRegType) { + case 0: + let LongReg = builder.LongRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (LongReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 1: + let DoubleReg = builder.DoubleRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (DoubleReg(st, uf, locals) != 0) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 2: + let StringReg = builder.StringRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + let str = StringReg(st, uf, locals); + if (str != null && !("" === (str))) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 3: + let StructReg = builder.StructRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (StructReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + case 4: + let NObjectReg = builder.NObjectRegister[checkRegIdx]; + builder.PushAction((st, uf, locals, pos) => { + if (NObjectReg(st, uf, locals) != null) { + return this.targetOffset; + } else { + return ++pos; + } + }); + break; + default: + throw Error("Unknown type " + this.checkRegType); + } + } + } + class DEC extends OBInstruction { + // regType; + // regIdx; + + init(code, builder, instructions, i) { + this.regType = ((code >> 20) & 0xf); + this.regIdx = ((code) & 0xfffff); + } + + link(builder, instructions, idx) { + let regIdx = this.regIdx; + switch (this.regType) { + case 0: + let LongReg = builder.LongRegister[regIdx]; + builder.LongRegister[regIdx] = (st, uf, locals) => { + let v = LongReg(st, uf, locals); + return v - 1; + }; + break; + case 1: + let DoubleReg = builder.DoubleRegister[regIdx]; + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + let v = DoubleReg(st, uf, locals); + return v - 1; + }; + break; + case 2: + case 3: + case 4: + default: + throw Error("Unsupport type " + this.regType); + } + } + } + class Reg2Var extends OBInstruction { + // type; + // varIdx; + // regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + let getLong = builder.LongRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.LongRegister[varIdx] = getLong(st, uf, locals); + return 1 + pos; + }); + break; + case 1: + let getDouble = builder.DoubleRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.DoubleRegister[varIdx] = getDouble(st, uf, locals); + return 1 + pos; + }); + break; + case 2: + let GetString = builder.StringRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StringRegister[varIdx] = GetString(st, uf, locals); + return 1 + pos; + }); + break; + case 3: + let getStruct = builder.StructRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.StructRegister[varIdx] = getStruct(st, uf, locals); + return 1 + pos; + }); + break; + case 4: + let getNObject = builder.NObjectRegister[regIdx]; + builder.PushAction((st, uf, locals, pos) => { + locals.NObjectRegister[varIdx] = getNObject(st, uf, locals); + return 1 + pos; + }); + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + class Var2Reg extends OBInstruction { + // type; + // varIdx; + // regIdx; + + init(code, builder, instructions, i) { + this.type = ((code >> 20) & 0xf); + this.regIdx = ((code >> 10) & 0x3ff); + this.varIdx = ((code) & 0x3ff); + } + + link(builder, instructions, idx) { + let varIdx = this.varIdx; + let regIdx = this.regIdx; + switch (this.type) { + case 0: + builder.LongRegister[regIdx] = (st, uf, locals) => { + return locals.LongRegister[varIdx]; + }; + break; + case 1: + builder.DoubleRegister[regIdx] = (st, uf, locals) => { + return locals.DoubleRegister[varIdx]; + }; + break; + case 2: + builder.StringRegister[regIdx] = (st, uf, locals) => { + return locals.StringRegister[varIdx]; + }; + break; + case 3: + builder.StructRegister[regIdx] = (st, uf, locals) => { + return locals.StructRegister[varIdx]; + }; + break; + case 4: + builder.NObjectRegister[regIdx] = (st, uf, locals) => { + return locals.NObjectRegister[varIdx]; + }; + break; + default: + throw Error("Unsupport type:" + this.type); + } + } + } + class I2F extends OBInstruction { + // intRegIdx; + // floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let getLong = builder.LongRegister[this.intRegIdx]; + builder.DoubleRegister[this.floatRegIdx] = (st, uf, locals) => { + return getLong(st, uf, locals); + }; + } + } + class EQ extends OBInstruction { + // ArgTypeId; + // LeftIdx; + // RightIdx; + // RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) === RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + class NEQ extends OBInstruction { + // ArgTypeId; + // LeftIdx; + // RightIdx; + // RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + /** + * + * @param {OBFunctionBuilder} builder + * @param {*} instructions + * @param {*} idx + */ + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + break; + case 3: + regArr = builder.StructRegister; + break; + case 4: + regArr = builder.NObjectRegister; + ; + break; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) != RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + class LT extends OBInstruction { + // ArgTypeId; + // LeftIdx; + // RightIdx; + // RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) < RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + class LTE extends OBInstruction { + // ArgTypeId; + // LeftIdx; + // RightIdx; + // RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) <= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + class GT extends OBInstruction { + // ArgTypeId; + // LeftIdx; + // RightIdx; + // RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) > RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + + class GTE extends OBInstruction { + // ArgTypeId; + // LeftIdx; + // RightIdx; + // RetIdx; + + init(code, builder, instructions, i) { + this.ArgTypeId = (code >> 20) & 0xF; + this.LeftIdx = (code >> 14) & 0x3f; + this.RightIdx = (code >> 7) & 0x7f; + this.RetIdx = code & 0x7f; + } + + link(builder, instructions, idx) { + let regArr; + switch (this.ArgTypeId) { + case 0: + regArr = builder.LongRegister; + break; + case 1: + regArr = builder.DoubleRegister; + break; + case 2: + regArr = builder.StringRegister; + return; + default: + throw Error("不支持类型:" + this.ArgTypeId); + } + let LeftReg = regArr[this.LeftIdx]; + let RightReg = regArr[this.RightIdx]; + builder.LongRegister[this.RetIdx] = (st, uf, locals) => { + return LeftReg(st, uf, locals) >= RightReg(st, uf, locals) ? 1 : 0; + }; + } + } + class DestroyFSM extends OBInstruction { + link(builder, instructions, idx) { + builder.PushAction((st, uf, locals, pos) => { + st.fsm.Destroy(); + throw new ChangeDestroyException(); + }); + } + } + class FSMBroadcastMsg extends OBInstruction { + // TitleIdx; + // BodyTypeID; + // BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + st.fsm.VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + return ++pos; + }); + } + /** + * + * @param {OBFunctionBuilder} builder + * @returns + */ + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + + /** + * 单元数操作 + */ + class SGLF extends OBInstruction { + // Opcode; + // value; + + init(code, builder, instructions, i) { + this.value = (code & 0xFFFF); + this.Opcode = (code >> 16) & 0xff; + } + + link(builder, instructions, idx) { + let value = this.value; + let f_value = builder.DoubleRegister[this.value]; + if (f_value == null) { + throw Error("left is null"); + } + switch (this.Opcode) { + case 0: + builder.DoubleRegister[value] = (s, f, l) => { + return -f_value(s, f, l); + }; + break; + case 1: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log(f_value(s, f, l)); + }; + break; + case 2: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.log10(f_value(s, f, l)); + }; + break; + case 3: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.exp(f_value(s, f, l)); + }; + break; + case 4: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.pow(10, f_value(s, f, l)); + }; + break; + case 5: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sqrt(f_value(s, f, l)); + }; + break; + case 6: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.abs(f_value(s, f, l)); + }; + break; + case 7: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.sin(f_value(s, f, l)); + }; + break; + case 8: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.cos(f_value(s, f, l)); + }; + break; + case 9: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.tan(f_value(s, f, l)); + }; + break; + case 10: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.asin(f_value(s, f, l)); + }; + break; + case 11: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.acos(f_value(s, f, l)); + }; + break; + case 12: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.atan(f_value(s, f, l)); + }; + break; + case 13: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.round(f_value(s, f, l)); + }; + break; + case 14: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.ceil(f_value(s, f, l)); + }; + break; + case 15: + builder.DoubleRegister[value] = (s, f, l) => { + return Math.floor(f_value(s, f, l)); + }; + break; + } + } + } + class RAND extends OBInstruction { + // Register; + + init(code, builder, instructions, i) { + this.Register = (code & 0xFFFFFF); + } + + link(builder, instructions, idx) { + builder.DoubleRegister[this.Register] = (st, f, l) => { + return Math.random(); + }; + } + } + class F2I extends OBInstruction { + // intRegIdx; + // floatRegIdx; + + init(code, builder, instructions, i) { + this.intRegIdx = ((code) >> 12) & 0xFFF; + this.floatRegIdx = ((code) & 0xFFF); + } + + link(builder, instructions, idx) { + let g = builder.DoubleRegister[this.floatRegIdx]; + builder.LongRegister[this.intRegIdx] = (st, uf, locals) => { + return Math.trunc(g(st, uf, locals)); + }; + } + } + class FSMSendMsgWait_Data extends OBInstruction { + // TitleIdx; + // TargetIdx; + // BodyTypeID; + // BodyRegisterIdx; + + init(code, builder, instructions, i) { + this.TargetIdx = ((code >> 17) & 0x7F); + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + this.BodyRegisterIdx = (code & 0x3F); + } + } + class FSMSendMsgWait extends OBInstruction { + // waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + } + + link(builder, instructions, idx) { + let anchor = instructions[idx - 1]; + if (!(anchor instanceof FSMSendMsgWait_Data)) { + throw Error("字节码错误"); + } + let f_title = builder.StringRegister[anchor.TitleIdx]; + let f_body = this.makeBody(builder, anchor.BodyTypeID, anchor.BodyRegisterIdx); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + let f_fsm = builder.NObjectRegister[anchor.TargetIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let FSM = st.fsm; + let fsm = f_fsm(st, uf, locals); + if (!fsm) { + FSM.VM.Log("未找到发送目标"); + return; + } + if (!(fsm instanceof OBVMFSM)) { + throw Error("字节码错误"); + } + fsm.VM.Schedule(waitSecond, (VM) => { + fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(anchor.BodyTypeID, body), body, FSM)); + }); + return ++pos; + }); + } + + makeBody(builder, BodyTypeID, BodyRegisterIdx) { + switch (BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + BodyTypeID); + } + } + } + class FSMBroadcastMsgWait extends OBInstruction { + // TitleIdx; + // BodyTypeID; + // BodyRegisterIdx; + // waitMilliSecondIdx; + + init(code, builder, instructions, i) { + this.TitleIdx = ((code >> 10) & 0x7F); + this.BodyTypeID = ((code >> 6) & 0xF); + + this.BodyRegisterIdx = (code & 0x3F); + this.waitMilliSecondIdx = ((code >> 17) & 0x3F); + ; + } + + link(builder, instructions, idx) { + let f_title = builder.StringRegister[this.TitleIdx]; + let f_body = this.makeBody(builder); + let waitTime = builder.LongRegister[this.waitMilliSecondIdx]; + builder.PushAction((st, uf, locals, pos) => { + let title = f_title(st, uf, locals); + let body = f_body(st, uf, locals); + let waitSecond = waitTime(st, uf, locals); + let fsm = st.fsm; + fsm.VM.Schedule(waitSecond, (VM) => { + VM.BroadcastMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, fsm)); + }); + return ++pos; + }); + } + + makeBody(builder) { + switch (this.BodyTypeID) { + case 0xF: + return (st, uf, locals) => null; + case 0: + var l = builder.LongRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return l(st, uf, locals); + }; + case 1: + var d = builder.DoubleRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return d(st, uf, locals); + }; + case 2: + var s = builder.StringRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s(st, uf, locals); + }; + case 3: + var s1 = builder.StructRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return s1(st, uf, locals); + }; + case 4: + var n = builder.NObjectRegister[this.BodyRegisterIdx]; + return (st, uf, locals) => { + return n(st, uf, locals); + }; + default: + throw Error("Unknown type " + this.BodyTypeID); + } + } + } + class TextJoin extends OBInstruction { + // Left; + // Right; + // RetReg; + + init(code, builder, instructions, i) { + this.Left = (code >> 17) & 0xFF; + this.Right = (code >> 9) & 0xff; + this.RetReg = (code & 0xFF); + } + + link(builder, instructions, idx) { + var l = builder.StringRegister[this.Left]; + var r = builder.StringRegister[this.Right]; + builder.StringRegister[this.RetReg] = (st, f, local) => { + return l(st, f, local) + r(st, f, local); + }; + } + } + class ToString extends OBInstruction { + // ValueType; + // ValueRegIdx; + // RetRegIdx; + + init(code, builder, instructions, i) { + this.ValueType = (code >> 20) & 0xF; + this.ValueRegIdx = (code >> 10) & 0x1ff; + this.RetRegIdx = (code & 0x1FF); + } + + link(builder, instructions, idx) { + switch (this.ValueType) { + case 0: + var getl = builder.LongRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getl(st, f, l).toString(); + }; + break; + case 1: + var getd = builder.DoubleRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + return getd(st, f, l).toString(); + }; + break; + case 2: + var getstr = builder.StringRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstr(st, f, l); + if (v == null) { + return ""; + } + return v; + }; + break; + case 3: + var getstruct = builder.StructRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = getstruct(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + case 4: + var geto = builder.NObjectRegister[this.ValueRegIdx]; + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + var v = geto(st, f, l); + if (v == null) { + return ""; + } + return v.toString(); + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + class Sender extends OBInstruction { + // RetReg; + + init(code, builder, instructions, i) { + this.RetReg = code & 0xFFFF; + } + + link(builder, instructions, idx) { + builder.NObjectRegister[this.RetReg] = (st, f, local) => { + return st.CurrentMessageSender(); + }; + } + } + class SHL extends OBInstruction { + // value; bitCount; + init(code, builder, instructions, i) { + this.bitCount = code & 0xFFF; + this.value = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.value]; + let getC = builder.LongRegister[this.bitCount]; + builder.LongRegister[this.value] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + if (c > 0) { + let r = v << c; + return r; + } else { + let r = v >> -c; + return r; + } + + }; + } + } + class AND extends OBInstruction { + // a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + let c = getC(st, f, l); + let r = v & c; + return r; + }; + } + } + class FIX extends OBInstruction { + // regType; regIdx; + init(code, builder, instructions, i) { + this.regIdx = code & 0xFFFFF; + this.regType = (code & 0xF00000) >> 20; + } + link(builder, instructions, idx) { + let v; + let loaded = false; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + let getV = builder[type][this.regIdx]; + builder[type][this.regIdx] = (st, f, l) => { + if (!loaded) { + v = getV(st, f, l); + } else { + loaded = true; + } + return v; + }; + } + } + /** + * value of may by key + */ + class VOM extends OBInstruction { + // map; + // key; + // ValueType; + // RetRegIdx; + init(code, builder, instructions, i) { + this.ValueType = code & 0x3F; + this.RetRegIdx = (code & (0x3f << 6)) >> 6; + this.key = (code & (0x3f << 12)) >> 12; + this.map = (code & (0x3f << 18)) >> 18; + } + + link(builder, instructions, idx) { + var getMap = builder.StructRegister[this.map]; + var getKey = builder.StringRegister[this.key]; + switch (this.ValueType) { + case 0: + builder.LongRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 1: + builder.DoubleRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 2: + builder.StringRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + case 3: + builder.StructRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + if (!v) { + debugger + } + return v; + }; + break; + case 4: + builder.NObjectRegister[this.RetRegIdx] = (st, f, l) => { + let m = getMap(st, f, l); + let k = getKey(st, f, l); + let v = m[k]; + return v; + }; + break; + default: + throw Error("Unknown type:" + this.ValueType); + } + } + } + class LAND extends OBInstruction { + // a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + let c = getC(st, f, l); + return c ? 1 : 0; + } else { + return 0; + } + }; + } + } + class LOR extends OBInstruction { + // a; b; + init(code, builder, instructions, i) { + this.b = code & 0xFFF; + this.a = (code & 0xFFF000) >> 12; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + let getC = builder.LongRegister[this.b]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + if (v) { + return 1; + } else { + let c = getC(st, f, l); + return c ? 1 : 0; + } + }; + } + } + class LNOT extends OBInstruction { + // a; + init(code, builder, instructions, i) { + this.a = code & 0xFFF; + } + link(builder, instructions, idx) { + let getV = builder.LongRegister[this.a]; + builder.LongRegister[this.a] = (st, f, l) => { + let v = getV(st, f, l); + return v === 0 ? 1 : 0; + }; + } + } + class COND extends OBInstruction { + // if_; then_; else_; regType; + init(code, builder, instructions, i) { + this.regType = code & 0x3F; + this.else_ = (code & (0x3f << 6)) >> 6; + this.then_ = (code & (0x3f << 12)) >> 12; + this.if_ = (code & (0x3f << 18)) >> 18; + } + link(builder, instructions, idx) { + let if_ = builder.LongRegister[this.if_]; + let else_; + let then_; + let type; + switch (this.regType) { + case 0: + type = 'LongRegister'; + break; + case 1: + type = 'DoubleRegister'; + break; + case 2: + type = 'StringRegister'; + break; + case 3: + type = 'StructRegister'; + break; + case 4: + type = 'NObjectRegister'; + break; + default: + throw Error("Unknown type:" + this.regType); + } + else_ = builder[type][this.else_]; + then_ = builder[type][this.then_]; + builder[type][this.then_] = (st, f, l) => { + let if_v = if_(st, f, l); + if (if_v != 0) { + return then_(st, f, l); + } + return else_(st, f, l); + }; + } + } + class NEW extends OBInstruction { + // StructDef; + // Register; + + init(code, builder, instructions, i) { + let stridx = code & 0xFFF; + this.Register = (code & 0xFF0000) >> 16; + + let structType = builder.loader.data.GetString(stridx); + let structDef = builder.loader.script.StructDef[structType]; + if (!structDef) { + throw Error('不存在数据结构 ' + structType); + } + this.StructDef = structDef; + } + + link(builder, instructions, idx) { + builder.StructRegister[this.Register] = this.getValue.bind(this); + } + + getValue(UBState, obvmfunction, TypedRegisters) { + let s = new OBStructValue(this.StructDef); + return s; + } + } + + export class OBStructDataSerializer { + relocation = new Relocation(); + /** + * + * @param {OBStructValue[]} valueData + * @returns {int[]} + */ + serialize(valueDataArray) { + let group = this.groupData(valueDataArray); + } + /** + * + * @param {OBStructValue[]} valueDataArray + * @returns {Object. { + let list = group[d.Def.Name]; + if (!list) { + list = []; + group[d.Def.Name] = list; + } + this.collData(d); + list.push(d); + }); + return group; + } + /** + * + * @param {OBStructValue} d + */ + collData(d) { + d.string.forEach(str => { + this.relocation.addRelocationString(str); + }); + d.registers.object.forEach(ofd => { + switch (ofd.type.$__type) { + case "StructFieldTypeStruct": + break; + case "StructFieldTypeIntegerMap": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + break; + case "StructFieldTypeStringMap": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + Object.keys(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + break; + case "StructFieldTypeList": + switch (ofd.type.elementType.name) { + case 'string': + case 'String': + Object.values(item.registers.object[ofd.registerIndex]).forEach(str => { + this.addRelocationString(str); + }); + } + break; + default: + console.error(ofd); + throw Error("功能未实现 " + ofd.type.$__type); + } + }); + } + } + // module.exports = { + // OBScriptLoader, + // OBVM + // } + export { + OBScriptLoader, + OBVM, + OBEventMessage, + OBMessage, + OBUserMessage + } + \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/i18n/en-US.json b/hap/entry/src/main/js/MainAbility/i18n/en-US.json index 08e34ea..55561b8 100644 --- a/hap/entry/src/main/js/MainAbility/i18n/en-US.json +++ b/hap/entry/src/main/js/MainAbility/i18n/en-US.json @@ -1,10 +1,7 @@ { "strings": { "hello": "Hello", - "world": "World", - "page": "Second Page", - "next": "Next Page", - "back": "Back" + "world": "World" }, "Files": { } diff --git a/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json b/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json index 3dd53b3..cce1af0 100644 --- a/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json +++ b/hap/entry/src/main/js/MainAbility/i18n/zh-CN.json @@ -1,10 +1,7 @@ { "strings": { "hello": "您好", - "world": "世界", - "page": "第二页", - "next": "下一页", - "back": "返回" + "world": "世界" }, "Files": { } diff --git a/hap/entry/src/main/js/MainAbility/pages/second/page.js b/hap/entry/src/main/js/MainAbility/pages/second/page.js index e77d8b6..67f72af 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/page.js +++ b/hap/entry/src/main/js/MainAbility/pages/second/page.js @@ -9,5 +9,14 @@ export default { this.info += "\n" + s; }, onclick: function () { + }, + pageStart:function(e){ + this.log('pageStart'); + }, + pageFinish:function(e){ + this.log('pageFinish'); + }, + pageError:function(e){ + this.log('pageError'); } } diff --git a/hap/entry/src/main/resources/base/element/string.json b/hap/entry/src/main/resources/base/element/string.json index 8dab0f2..1fd213e 100644 --- a/hap/entry/src/main/resources/base/element/string.json +++ b/hap/entry/src/main/resources/base/element/string.json @@ -1,12 +1,16 @@ { "string": [ { - "name": "entry_MainAbility", - "value": "OpenBlock" + "name": "entry_desc", + "value": "OpenBlock for OpenHarmony HAP" + }, + { + "name": "MainAbility_desc", + "value": "OpenBlock for OpenHarmony HAP" }, { - "name": "description_mainability", - "value": "OpenBlock Ability" + "name": "MainAbility_label", + "value": "OpenBlock" } ] } \ No newline at end of file diff --git a/hap/hvigorfile.js b/hap/hvigorfile.js new file mode 100644 index 0000000..cff9f0d --- /dev/null +++ b/hap/hvigorfile.js @@ -0,0 +1,2 @@ +// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently. +module.exports = require('@ohos/hvigor-ohos-plugin').legacyAppTasks \ No newline at end of file diff --git a/hap/local.properties b/hap/local.properties index 852ef8d..30ce720 100644 --- a/hap/local.properties +++ b/hap/local.properties @@ -1,13 +1,10 @@ -## This file is automatically generated by DevEco Studio. +# This file is automatically generated by DevEco Studio. # Do not modify this file -- YOUR CHANGES WILL BE ERASED! # -# This file must *NOT* be checked into Version Control Systems, +# This file should *NOT* be checked into Version Control Systems, # as it contains information specific to your local configuration. # -# Location of the SDK. This is only used by Gradle. -# For customization when using a Version Control System, please read the -# header note. -#Fri Feb 25 02:49:49 CST 2022 -sdk.dir=C\:\\Users\\Administrator\\AppData\\Local\\OpenHarmony\\Sdk -nodejs.dir=C\:\\Program Files\\Huawei\\DevEco Studio 3.0.0.601\\tools\\nodejs -npm.dir=C\:\\Program Files\\Huawei\\DevEco Studio 3.0.0.601\\tools\\nodejs +# For customization when using a Version Control System, please read the header note. +sdk.dir=C:/Users/Administrator/AppData/Local/OpenHarmony/Sdk +nodejs.dir=C:/Program Files/Huawei/DevEco Studio 3.0.0.900/tools/nodejs +npm.dir=C:/Program Files/Huawei/DevEco Studio 3.0.0.900/tools/nodejs diff --git a/hap/package-lock.json b/hap/package-lock.json new file mode 100644 index 0000000..aa00017 --- /dev/null +++ b/hap/package-lock.json @@ -0,0 +1,1643 @@ +{ + "name": "openblock", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@ohos/hvigor": { + "version": "1.0.6", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor/-/@ohos/hvigor-1.0.6.tgz", + "integrity": "sha512-jjp7vpvUOMW1Nf7TdyhOtonwWHoSyBJLUiZTQqIx/GJV4UJyIqsiURUOqFwncQ4L7PDdeHuWly4uEelknYeWhg==", + "requires": { + "@ohos/hvigor-base": "1.0.6", + "interpret": "1.4.0", + "liftoff": "4.0.0", + "mute-stdout": "1.0.0", + "pretty-hrtime": "1.0.0", + "v8flags": "3.2.0", + "yargs": "7.1.0" + } + }, + "@ohos/hvigor-base": { + "version": "1.0.6", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor-base/-/@ohos/hvigor-base-1.0.6.tgz", + "integrity": "sha512-cRDnWICTxmpNiFb9clIioqP5Oik1seLCICztXVhZqultrHuxwTheCRUZrHwlpyWdkSB2Al+FFBqmSwzIgZX4IQ==", + "requires": { + "json5": "2.2.0", + "log4js": "6.4.1", + "undertaker": "1.2.1" + } + }, + "@ohos/hvigor-ohos-plugin": { + "version": "1.0.6", + "resolved": "https://repo.harmonyos.com/npm/@ohos/hvigor-ohos-plugin/-/@ohos/hvigor-ohos-plugin-1.0.6.tgz", + "integrity": "sha512-MAAi8uJxMzODUoSSNfBr+fU4HQ20dfQtkje9I+X4asc7qY2kAplW/q9f5XS8IOvv8zhC8OcSgsAXOAJuLMstOQ==", + "requires": { + "@ohos/hvigor-base": "1.0.6", + "@ohos/sdkmanager-common": "1.1.3", + "ajv": "8.10.0", + "archiver": "5.3.0", + "execa": "5.1.1", + "fs-extra": "10.0.0", + "glob": "7.2.0", + "iconv-lite": "0.6.3", + "json5": "2.2.0", + "lodash": "4.17.21", + "pretty-hrtime": "1.0.3", + "resolve-package-path": "4.0.3" + }, + "dependencies": { + "fs-extra": { + "version": "10.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=" + } + } + }, + "@ohos/sdkmanager-common": { + "version": "1.1.3", + "resolved": "https://repo.harmonyos.com/npm/@ohos/sdkmanager-common/-/@ohos/sdkmanager-common-1.1.3.tgz", + "integrity": "sha512-d2uhVauDDJZIUvyyaWWoavG4N/jLyfF5IH5kEXKV6R8HNf3606H1zDQzA+UZtOfwwJFXhD9djRjnVFNB8xc7aw==" + }, + "ajv": { + "version": "8.10.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/ajv/-/ajv-8.10.0.tgz", + "integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==", + "requires": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "archiver": { + "version": "5.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/archiver/-/archiver-5.3.0.tgz", + "integrity": "sha512-iUw+oDwK0fgNpvveEsdQ0Ase6IIKztBJU2U0E9MzszMfmVVUyv1QJhS2ITW9ZCqx8dktAxVAjWWkKehuZE8OPg==", + "requires": { + "archiver-utils": "^2.1.0", + "async": "^3.2.0", + "buffer-crc32": "^0.2.1", + "readable-stream": "^3.6.0", + "readdir-glob": "^1.0.0", + "tar-stream": "^2.2.0", + "zip-stream": "^4.1.0" + } + }, + "archiver-utils": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/archiver-utils/-/archiver-utils-2.1.0.tgz", + "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", + "requires": { + "glob": "^7.1.4", + "graceful-fs": "^4.2.0", + "lazystream": "^1.0.0", + "lodash.defaults": "^4.2.0", + "lodash.difference": "^4.5.0", + "lodash.flatten": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.union": "^4.6.0", + "normalize-path": "^3.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "arr-filter": { + "version": "1.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/arr-filter/-/arr-filter-1.1.2.tgz", + "integrity": "sha1-Q/3d0JHo7xGqTEXZzcGOLf8XEe4=", + "requires": { + "make-iterator": "^1.0.0" + } + }, + "arr-flatten": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/arr-flatten/-/arr-flatten-1.1.0.tgz", + "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==" + }, + "arr-map": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/arr-map/-/arr-map-2.0.2.tgz", + "integrity": "sha1-Onc0X/wc814qkYJWAfnljy4kysQ=", + "requires": { + "make-iterator": "^1.0.0" + } + }, + "array-each": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-each/-/array-each-1.0.1.tgz", + "integrity": "sha1-p5SvDAWrF1KEbudTofIRoFugxE8=" + }, + "array-initial": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-initial/-/array-initial-1.1.0.tgz", + "integrity": "sha1-L6dLJnOTccOUe9enrcc74zSz15U=", + "requires": { + "array-slice": "^1.0.0", + "is-number": "^4.0.0" + } + }, + "array-last": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-last/-/array-last-1.3.0.tgz", + "integrity": "sha512-eOCut5rXlI6aCOS7Z7kCplKRKyiFQ6dHFBem4PwlwKeNFk2/XxTrhRh5T9PyaEWGy/NHTZWbY+nsZlNFJu9rYg==", + "requires": { + "is-number": "^4.0.0" + } + }, + "array-slice": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/array-slice/-/array-slice-1.1.0.tgz", + "integrity": "sha512-B1qMD3RBP7O8o0H2KbrXDyB0IccejMF15+87Lvlor12ONPRHP6gTjXMNkt/d3ZuOGbAe66hFmaCfECI24Ufp6w==" + }, + "async": { + "version": "3.2.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/async/-/async-3.2.3.tgz", + "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" + }, + "async-done": { + "version": "1.3.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/async-done/-/async-done-1.3.2.tgz", + "integrity": "sha512-uYkTP8dw2og1tu1nmza1n1CMW0qb8gWWlwqMmLb7MhBVs4BXrFziT6HXUd+/RlRA/i4H9AkofYloUbs1fwMqlw==", + "requires": { + "end-of-stream": "^1.1.0", + "once": "^1.3.2", + "process-nextick-args": "^2.0.0", + "stream-exhaust": "^1.0.1" + } + }, + "async-settle": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/async-settle/-/async-settle-1.0.0.tgz", + "integrity": "sha1-HQqRS7Aldb7IqPOnTlCA9yssDGs=", + "requires": { + "async-done": "^1.2.2" + } + }, + "bach": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/bach/-/bach-1.2.0.tgz", + "integrity": "sha1-Szzpa/JxNPeaG0FKUcFONMO9mIA=", + "requires": { + "arr-filter": "^1.1.1", + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "array-each": "^1.0.0", + "array-initial": "^1.0.0", + "array-last": "^1.1.1", + "async-done": "^1.2.2", + "async-settle": "^1.0.0", + "now-and-later": "^2.0.0" + } + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" + }, + "bl": { + "version": "4.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-crc32": { + "version": "0.2.13", + "resolved": "https://repo.huaweicloud.com/repository/npm/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" + }, + "call-bind": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "requires": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + } + }, + "camelcase": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/camelcase/-/camelcase-3.0.0.tgz", + "integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo=" + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "collection-map": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/collection-map/-/collection-map-1.0.0.tgz", + "integrity": "sha1-rqDwb40mx4DCt1SUOFVEsiVa8Yw=", + "requires": { + "arr-map": "^2.0.2", + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "compress-commons": { + "version": "4.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/compress-commons/-/compress-commons-4.1.1.tgz", + "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", + "requires": { + "buffer-crc32": "^0.2.13", + "crc32-stream": "^4.0.2", + "normalize-path": "^3.0.0", + "readable-stream": "^3.6.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "crc-32": { + "version": "1.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==" + }, + "crc32-stream": { + "version": "4.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/crc32-stream/-/crc32-stream-4.0.2.tgz", + "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", + "requires": { + "crc-32": "^1.2.0", + "readable-stream": "^3.4.0" + } + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "date-format": { + "version": "4.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/date-format/-/date-format-4.0.6.tgz", + "integrity": "sha512-B9vvg5rHuQ8cbUXE/RMWMyX2YA5TecT3jKF5fLtGNlzPlU7zblSPmAm2OImDbWL+LDOQ6pUm+4LOFz+ywS41Zw==" + }, + "debug": { + "version": "4.3.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "default-resolution": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/default-resolution/-/default-resolution-2.0.0.tgz", + "integrity": "sha1-vLgrqnKtebQmp2cy8aga1t8m1oQ=" + }, + "define-properties": { + "version": "1.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/define-properties/-/define-properties-1.1.3.tgz", + "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", + "requires": { + "object-keys": "^1.0.12" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=" + }, + "end-of-stream": { + "version": "1.4.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "requires": { + "once": "^1.4.0" + } + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.60", + "resolved": "https://repo.huaweicloud.com/repository/npm/es5-ext/-/es5-ext-0.10.60.tgz", + "integrity": "sha512-jpKNXIt60htYG59/9FGf2PYT3pwMpnEbNKysU+k/4FGwyGtMotOvcZOuW+EmXXYASRqYSXQfGL5cVIthOTgbkg==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "execa": { + "version": "5.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-up": { + "version": "1.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/find-up/-/find-up-1.1.2.tgz", + "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", + "requires": { + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "findup-sync": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/findup-sync/-/findup-sync-5.0.0.tgz", + "integrity": "sha512-MzwXju70AuyflbgeOhzvQWAvvQdo1XL0A9bVvlXsYcFEBM87WR4OakL4OfZq+QRmr+duJubio+UtNQCPsVESzQ==", + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.3", + "micromatch": "^4.0.4", + "resolve-dir": "^1.0.1" + } + }, + "fined": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fined/-/fined-2.0.0.tgz", + "integrity": "sha512-OFRzsL6ZMHz5s0JrsEr+TpdGNCtrVtnuG3x1yzGNiQHT0yaDnXAj8V/lWcpJVrnoDpcwXcASxAZYbuXda2Y82A==", + "requires": { + "expand-tilde": "^2.0.2", + "is-plain-object": "^5.0.0", + "object.defaults": "^1.1.0", + "object.pick": "^1.3.0", + "parse-filepath": "^1.0.2" + } + }, + "flagged-respawn": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/flagged-respawn/-/flagged-respawn-2.0.0.tgz", + "integrity": "sha512-Gq/a6YCi8zexmGHMuJwahTGzXlAZAOsbCVKduWXC6TlLCjjFRlExMJc4GC2NYPYZ0r/brw9P7CpRgQmlPVeOoA==" + }, + "flatted": { + "version": "3.2.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/flatted/-/flatted-3.2.5.tgz", + "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==" + }, + "for-in": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/for-in/-/for-in-1.0.2.tgz", + "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=" + }, + "for-own": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/for-own/-/for-own-1.0.0.tgz", + "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", + "requires": { + "for-in": "^1.0.1" + } + }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" + }, + "fs-extra": { + "version": "10.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs-extra/-/fs-extra-10.0.1.tgz", + "integrity": "sha512-NbdoVMZso2Lsrn/QwLXOy6rm0ufY2zEOKCDzJR/0kBsb0E6qed0P3iYK+Ath3BfvXEeu4JhEtXLgILx5psUfag==", + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-intrinsic": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-intrinsic/-/get-intrinsic-1.1.1.tgz", + "integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==", + "requires": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1" + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==" + }, + "glob": { + "version": "7.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://repo.huaweicloud.com/repository/npm/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" + }, + "has": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-symbols": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://repo.huaweicloud.com/repository/npm/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==" + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==" + }, + "hypium": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/hypium/-/hypium-1.0.0.tgz", + "integrity": "sha512-nl+RQVv2AU/5FvFRhsXyWO5wh+2huhdqRZ3bszBWZzW+kpNI3AT4ydvVRYIfaQbYwV4UlX/rSc7BtFjLAezhow==" + }, + "iconv-lite": { + "version": "0.6.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "ini": { + "version": "1.3.8", + "resolved": "https://repo.huaweicloud.com/repository/npm/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "interpret": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/interpret/-/interpret-1.4.0.tgz", + "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "is-absolute": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-absolute/-/is-absolute-1.0.0.tgz", + "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", + "requires": { + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-core-module": { + "version": "2.8.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-core-module/-/is-core-module-2.8.1.tgz", + "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, + "is-relative": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-relative/-/is-relative-1.0.0.tgz", + "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", + "requires": { + "is-unc-path": "^1.0.0" + } + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==" + }, + "is-unc-path": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-unc-path/-/is-unc-path-1.0.0.tgz", + "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", + "requires": { + "unc-path-regex": "^0.1.2" + } + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=" + }, + "json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" + }, + "json5": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/json5/-/json5-2.2.0.tgz", + "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==", + "requires": { + "minimist": "^1.2.5" + } + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==" + }, + "last-run": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/last-run/-/last-run-1.1.1.tgz", + "integrity": "sha1-RblpQsF7HHnHchmCWbqUO+v4yls=", + "requires": { + "default-resolution": "^2.0.0", + "es6-weak-map": "^2.0.1" + } + }, + "lazystream": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + } + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "liftoff": { + "version": "4.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/liftoff/-/liftoff-4.0.0.tgz", + "integrity": "sha512-rMGwYF8q7g2XhG2ulBmmJgWv25qBsqRbDn5gH0+wnuyeFt7QBJlHJmtg5qEdn4pN6WVAUMgXnIxytMFRX9c1aA==", + "requires": { + "extend": "^3.0.2", + "findup-sync": "^5.0.0", + "fined": "^2.0.0", + "flagged-respawn": "^2.0.0", + "is-plain-object": "^5.0.0", + "object.map": "^1.0.1", + "rechoir": "^0.8.0", + "resolve": "^1.20.0" + } + }, + "load-json-file": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "lodash.defaults": { + "version": "4.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash.defaults/-/lodash.defaults-4.2.0.tgz", + "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw=" + }, + "lodash.difference": { + "version": "4.5.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash.difference/-/lodash.difference-4.5.0.tgz", + "integrity": "sha1-nMtOUF1Ia5FlE0V3KIWi3yf9AXw=" + }, + "lodash.flatten": { + "version": "4.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash.flatten/-/lodash.flatten-4.4.0.tgz", + "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.union": { + "version": "4.6.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/lodash.union/-/lodash.union-4.6.0.tgz", + "integrity": "sha1-SLtQiECfFvGCFmZkHETdGqrjzYg=" + }, + "log4js": { + "version": "6.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/log4js/-/log4js-6.4.1.tgz", + "integrity": "sha512-iUiYnXqAmNKiIZ1XSAitQ4TmNs8CdZYTAWINARF3LjnsLN8tY5m0vRwd6uuWj/yNY0YHxeZodnbmxKFUOM2rMg==", + "requires": { + "date-format": "^4.0.3", + "debug": "^4.3.3", + "flatted": "^3.2.4", + "rfdc": "^1.3.0", + "streamroller": "^3.0.2" + } + }, + "make-iterator": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/make-iterator/-/make-iterator-1.0.1.tgz", + "integrity": "sha512-pxiuXh0iVEq7VM7KMIhs5gxsfxCux2URptUQaXo4iZZJxBAzTPOLE2BumO5dbfVYq/hBJFBR/a1mFDmOx5AGmw==", + "requires": { + "kind-of": "^6.0.2" + } + }, + "map-cache": { + "version": "0.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/map-cache/-/map-cache-0.2.2.tgz", + "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=" + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" + }, + "micromatch": { + "version": "4.0.5", + "resolved": "https://repo.huaweicloud.com/repository/npm/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "requires": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" + }, + "ms": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "mute-stdout": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/mute-stdout/-/mute-stdout-1.0.0.tgz", + "integrity": "sha1-WzLqB+tDyd7WEwQ0z5JvRrKn/U0=" + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "normalize-path": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" + }, + "now-and-later": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/now-and-later/-/now-and-later-2.0.1.tgz", + "integrity": "sha512-KGvQ0cB70AQfg107Xvs/Fbu+dGmZoTRJp2TaPwcwQm3/7PteUyN2BCgk8KBMPGBUXZdVwyWS8fDCGFygBm19UQ==", + "requires": { + "once": "^1.3.2" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "requires": { + "path-key": "^3.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "object-keys": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" + }, + "object.assign": { + "version": "4.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.assign/-/object.assign-4.1.2.tgz", + "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==", + "requires": { + "call-bind": "^1.0.0", + "define-properties": "^1.1.3", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + } + }, + "object.defaults": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.defaults/-/object.defaults-1.1.0.tgz", + "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", + "requires": { + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.map": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.map/-/object.map-1.0.1.tgz", + "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "object.pick": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.pick/-/object.pick-1.3.0.tgz", + "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", + "requires": { + "isobject": "^3.0.1" + } + }, + "object.reduce": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/object.reduce/-/object.reduce-1.0.1.tgz", + "integrity": "sha1-b+NI8qx/oPlcpiEiZZkJaCW7A60=", + "requires": { + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" + } + }, + "once": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "parse-filepath": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-filepath/-/parse-filepath-1.0.2.tgz", + "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", + "requires": { + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" + } + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=" + }, + "path-exists": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-exists/-/path-exists-2.1.0.tgz", + "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", + "requires": { + "pinkie-promise": "^2.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "path-root": { + "version": "0.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root/-/path-root-0.1.1.tgz", + "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", + "requires": { + "path-root-regex": "^0.1.0" + } + }, + "path-root-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-root-regex/-/path-root-regex-0.1.2.tgz", + "integrity": "sha1-v8zcjfWxLcUsi0PsONGNcsBLqW0=" + }, + "path-type": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", + "requires": { + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "picomatch": { + "version": "2.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=" + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "requires": { + "pinkie": "^2.0.0" + } + }, + "pretty-hrtime": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/pretty-hrtime/-/pretty-hrtime-1.0.0.tgz", + "integrity": "sha1-9ualItPmBwRSK/Db5oVu0g515Nw=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "read-pkg": { + "version": "1.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", + "requires": { + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" + } + }, + "read-pkg-up": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", + "requires": { + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "readdir-glob": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/readdir-glob/-/readdir-glob-1.1.1.tgz", + "integrity": "sha512-91/k1EzZwDx6HbERR+zucygRFfiPl2zkIYZtv3Jjr6Mn7SkKcVct8aVO+sSRiGMc6fLf72du3d92/uY63YPdEA==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "rechoir": { + "version": "0.8.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "requires": { + "resolve": "^1.20.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "resolve": { + "version": "1.22.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve/-/resolve-1.22.0.tgz", + "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", + "requires": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-package-path": { + "version": "4.0.3", + "resolved": "https://repo.huaweicloud.com/repository/npm/resolve-package-path/-/resolve-package-path-4.0.3.tgz", + "integrity": "sha512-SRpNAPW4kewOaNUt8VPqhJ0UMxawMwzJD8V7m1cJfdSTK9ieZwS6K7Dabsm4bmLFM96Z5Y/UznrpG5kt1im8yA==", + "requires": { + "path-root": "^0.1.1" + } + }, + "rfdc": { + "version": "1.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "semver": { + "version": "5.7.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://repo.huaweicloud.com/repository/npm/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==" + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.11", + "resolved": "https://repo.huaweicloud.com/repository/npm/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz", + "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==" + }, + "stream-exhaust": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/stream-exhaust/-/stream-exhaust-1.0.2.tgz", + "integrity": "sha512-b/qaq/GlBK5xaq1yrK9/zFcyRSTNxmcZwFLGSTG0mXgZl/4Z6GgiyYOXOvY7N3eEvFRAG1bkDRz5EPGSvPYQlw==" + }, + "streamroller": { + "version": "3.0.6", + "resolved": "https://repo.huaweicloud.com/repository/npm/streamroller/-/streamroller-3.0.6.tgz", + "integrity": "sha512-Qz32plKq/MZywYyhEatxyYc8vs994Gz0Hu2MSYXXLD233UyPeIeRBZARIIGwFer4Mdb8r3Y2UqKkgyDghM6QCg==", + "requires": { + "date-format": "^4.0.6", + "debug": "^4.3.4", + "fs-extra": "^10.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==" + }, + "supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" + }, + "tar-stream": { + "version": "2.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "requires": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "requires": { + "is-number": "^7.0.0" + }, + "dependencies": { + "is-number": { + "version": "7.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==" + } + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "unc-path-regex": { + "version": "0.1.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/unc-path-regex/-/unc-path-regex-0.1.2.tgz", + "integrity": "sha1-5z3T17DXxe2G+6xrCufYxqadUPo=" + }, + "undertaker": { + "version": "1.2.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/undertaker/-/undertaker-1.2.1.tgz", + "integrity": "sha512-71WxIzDkgYk9ZS+spIB8iZXchFhAdEo2YU8xYqBYJ39DIUIqziK78ftm26eecoIY49X0J2MLhG4hr18Yp6/CMA==", + "requires": { + "arr-flatten": "^1.0.1", + "arr-map": "^2.0.0", + "bach": "^1.0.0", + "collection-map": "^1.0.0", + "es6-weak-map": "^2.0.1", + "last-run": "^1.1.0", + "object.defaults": "^1.0.0", + "object.reduce": "^1.0.0", + "undertaker-registry": "^1.0.0" + } + }, + "undertaker-registry": { + "version": "1.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/undertaker-registry/-/undertaker-registry-1.0.1.tgz", + "integrity": "sha1-XkvaMI5KiirlhPm5pDWaSZglzFA=" + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "v8flags": { + "version": "3.2.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/v8flags/-/v8flags-3.2.0.tgz", + "integrity": "sha512-mH8etigqMfiGWdeXpaaqGfs6BndypxusHHcv2qSHyZkGEznCd/qAXCWWRzeowtL54147cktFOC4P5y+kl8d8Jg==", + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://repo.huaweicloud.com/repository/npm/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "1.0.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/which-module/-/which-module-1.0.0.tgz", + "integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8=" + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "y18n": { + "version": "3.2.2", + "resolved": "https://repo.huaweicloud.com/repository/npm/y18n/-/y18n-3.2.2.tgz", + "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==" + }, + "yargs": { + "version": "7.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs/-/yargs-7.1.0.tgz", + "integrity": "sha1-a6MY6xaWFyf10oT46gA+jWFU0Mg=", + "requires": { + "camelcase": "^3.0.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^1.4.0", + "read-pkg-up": "^1.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^1.0.2", + "which-module": "^1.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^5.0.0" + } + }, + "yargs-parser": { + "version": "5.0.1", + "resolved": "https://repo.huaweicloud.com/repository/npm/yargs-parser/-/yargs-parser-5.0.1.tgz", + "integrity": "sha512-wpav5XYiddjXxirPoCTUPbqM0PXvJ9hiBMvuJgInvo4/lAOTZzUprArw17q2O1P2+GHhbBr18/iQwjL5Z9BqfA==", + "requires": { + "camelcase": "^3.0.0", + "object.assign": "^4.1.0" + } + }, + "zip-stream": { + "version": "4.1.0", + "resolved": "https://repo.huaweicloud.com/repository/npm/zip-stream/-/zip-stream-4.1.0.tgz", + "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", + "requires": { + "archiver-utils": "^2.1.0", + "compress-commons": "^4.1.0", + "readable-stream": "^3.6.0" + } + } + } +} diff --git a/hap/package.json b/hap/package.json index 0967ef4..7fea95c 100644 --- a/hap/package.json +++ b/hap/package.json @@ -1 +1,18 @@ -{} +{ + "license":"ISC", + "devDependencies":{}, + "name":"openblock", + "ohos":{ + "org":"huawei", + "directoryLevel":"project", + "buildTool":"hvigor" + }, + "description":"example description", + "repository":{}, + "version":"1.0.0", + "dependencies":{ + "@ohos/hvigor-ohos-plugin":"1.0.6", + "hypium":"^1.0.0", + "@ohos/hvigor":"1.0.6" + } +} \ No newline at end of file -- Gitee From 78d46bcfea3674c99beda335ae4d505b9bc767a0 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sun, 10 Apr 2022 02:42:07 +0800 Subject: [PATCH 25/30] =?UTF-8?q?3.1=20release=20=E6=89=93=E5=BC=80?= =?UTF-8?q?=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hap/entry/src/main/config.json | 5 +- .../main/js/MainAbility/common/runtime/vm.js | 65 +++++++++++------ .../main/js/MainAbility/pages/index/index.hml | 8 ++- .../main/js/MainAbility/pages/index/index.js | 70 +++++++++++-------- 4 files changed, 93 insertions(+), 55 deletions(-) diff --git a/hap/entry/src/main/config.json b/hap/entry/src/main/config.json index f09c9bf..6844e90 100644 --- a/hap/entry/src/main/config.json +++ b/hap/entry/src/main/config.json @@ -12,6 +12,9 @@ "reqPermissions": [ { "name": "ohos.permission.WRITE_MEDIA" + }, + { + "name": "ohos.permission.INTERNET" } ], "package": "com.openblock.ohos", @@ -50,7 +53,7 @@ "formsEnabled": false, "label": "$string:MainAbility_label", "type": "page", - "launchType": "standard" + "launchType": "singleton" } ], "js": [ diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index a767285..0f30d7a 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -29,7 +29,7 @@ static objFieldGetter(fieldName, fieldRegister) { return (builder, args) => { let obj = builder.NObjectRegister[args[1] & 0xfff]; - builder[fieldRegister][args[1] & 0xfff] = (st, f, local) => { + builder[fieldRegister][args[0] & 0xfff] = (st, f, local) => { return obj(st, f, local)[fieldName]; }; }; @@ -38,9 +38,10 @@ * * @param {Function} func * @param {Number[]} argtype + * @param {Boolean} addVMarg * @returns */ - static closureVoid(func, argtype) { + static closureVoid(func, argtype, addVMarg) { /** * * @param {OBFunctionBuilder} builder @@ -61,6 +62,12 @@ }); builder.PushAction((st, f, local, pos) => { let argVals = argGetters.map(g => g(st, f, local)); + if (addVMarg) { + argVals.push(st); + argVals.push(f); + argVals.push(local); + argVals.push(pos); + } func.apply(null, argVals); return pos + 1; }); @@ -310,7 +317,7 @@ case 15: return new MethodCall(); case 16: - return new MethodCallRegisterInfoAnchor(); + return new ExtInfo(); case 17: return new CreateFSM(); case 18: @@ -1522,11 +1529,6 @@ } let fsmdata = this.script.FullNameFSMData[name]; if (!fsmdata) { - for(let key in this.script.FullNameFSMData){ - if(key === name){ - return this.script.FullNameFSMData[key]; - } - } return null; } let uBFSM = new OBVMFSM(this, fsmdata); @@ -2110,12 +2112,20 @@ if (arg.constructor === OBVMFSM) { return "FSM"; } else { + console.warn("should not get type name of native type"); if (arg.constructor) { return arg.constructor.name; } else { - return typeof (arg); + throw Error('Can not get type name of native type'); } } + // case 4: + // console.warn("should not get type name of native type"); + // if (arg.constructor) { + // return arg.constructor.name; + // }else{ + // throw Error('Can not get type name of native type'); + // } default: throw Error("Unknown type:" + typeId); } @@ -2132,8 +2142,6 @@ } catch (err) { if (!(err instanceof VMInterruptException)) { - state.fsm.VM.Output(err); - state.fsm.VM.Output(err.stack); console.error(err); throw err; } @@ -2151,8 +2159,8 @@ state.HandleMessage(this); } catch (err) { if (!(err instanceof VMInterruptException)) { - state.fsm.VM.Output(err); - state.fsm.VM.Output(err.stack); + state.fsm.VM.Output(err); + state.fsm.VM.Output(err.stack); console.error(err); throw err; } @@ -2508,11 +2516,11 @@ }); } } - class MethodCallRegisterInfoAnchor extends OBInstruction { + class ExtInfo extends OBInstruction { // RegisterInfoIdx; init(code, builder, instructions, i) { - this.RegisterInfoIdx = code & 0xFFFF; + this.info = code & 0xFFFF; } } class NativeMethodCall extends OBInstruction { @@ -2525,10 +2533,10 @@ link(builder, instructions, idx) { let LibName = builder.loader.data.GetString(this.LibNameIdx); let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + if (!(anchor instanceof ExtInfo)) { + throw Error("last cmd is not ExtInfo"); } - let RegisterInfoIdx = anchor.RegisterInfoIdx; + let RegisterInfoIdx = anchor.info; let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); let funcIdx = args[0]; let _args = args.slice(1); @@ -2615,10 +2623,10 @@ link(builder, instructions, idx) { let MethodName = builder.loader.data.GetString(this.MethodNameIdx); let anchor = instructions[idx - 1]; - if (!(anchor instanceof MethodCallRegisterInfoAnchor)) { - throw Error("last cmd is not MethodCallRegisterInfoAnchor"); + if (!(anchor instanceof ExtInfo)) { + throw Error("last cmd is not ExtInfo"); } - let RegisterInfoIdx = anchor.RegisterInfoIdx; + let RegisterInfoIdx = anchor.info; let args = builder.loader.data.GetInt32FromBin(RegisterInfoIdx); let uf1 = builder.loader.script.loadedFunctions[MethodName]; @@ -3103,6 +3111,13 @@ this.BodyTypeID = ((code >> 6) & 0xF); this.BodyRegisterIdx = (code & 0x3F); + if (this.BodyTypeID == 4) { + let typedata = instructions[i - 1]; + if (!(typedata instanceof ExtInfo)) { + throw Error("last cmd is not ExtInfo"); + } + this.TypeName = builder.loader.data.GetString(typedata.info); + } } /** * @@ -3119,7 +3134,13 @@ if (fsm) { let title = f_title(st, uf, locals); let body = f_body(st, uf, locals); - fsm.PostMessage(new OBUserMessage(title, OBMessage.ArgTypeOf(this.BodyTypeID, body), body, st.fsm)); + let typename; + if (this.BodyTypeID == 4) { + typename = this.TypeName; + } else { + typename = OBMessage.ArgTypeOf(this.BodyTypeID, body); + } + fsm.PostMessage(new OBUserMessage(title, typename, body, st.fsm)); } return ++pos; }); diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.hml b/hap/entry/src/main/js/MainAbility/pages/index/index.hml index 93bfda8..2c76483 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.hml +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.hml @@ -19,14 +19,18 @@ -->
-
+
{{ info }}
+ + + +
- +
\ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index e7833e4..eb3c3cb 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -16,6 +16,7 @@ import router from '@system.router'; import fileio from '@ohos.fileio'; import * as obvm from '../../common/runtime/vm.js'; import * as obcanvaslib from '../../common/canvas.js' +import featureAbility from '@ohos.ability.featureAbility' import prompt from '@system.prompt'; import app from '@system.app'; @@ -100,40 +101,49 @@ export default { this.ob_event("swipe"); }, initStage() { - let stage = this.$refs.canvas1; - try { - console.log('openblock 中文'+'测试'); - // /storage/media/100/local/files - filepath = "/data/storage/el1/base/main.xe";//"/data/"+app.getInfo().appID+"/main.xe"; - this.log(filepath); - stage.width = stage.width; - let fd = fileio.openSync(filepath, 0o2); - let st = fileio.fstatSync(fd); - let scriptArrayBuffer = new ArrayBuffer(st.size); - fileio.readSync(fd, scriptArrayBuffer); + var context = featureAbility.getContext(); + context.getOrCreateLocalDir().then((dir) => { + this.log("root dir=" + dir); + let stage = this.$refs.canvas1; + + try { + console.log('openblock 中文'+'测试'); + // /storage/media/100/local/files - let obcanvas = new obcanvaslib.OBCanvas2D(stage); - // let ctx = stage.getContext('2d'); - // ctx.fillRect(15, 15, 50, 50); + filepath = dir + "/main.xe";//"/data/"+app.getInfo().appID+"/main.xe"; + this.log(filepath); + stage.width = stage.width; + let fd = fileio.openSync(filepath, 0o2); + let st = fileio.fstatSync(fd); + let scriptArrayBuffer = new ArrayBuffer(st.size); + fileio.readSync(fd, scriptArrayBuffer); - let nativeLibs = [obcanvas.install.bind(obcanvas)]; - let loader = obvm.OBScriptLoader; - let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); - this.vm = new obvm.OBVM(loadedScript,{setTimeout:setTimeout,Output:this.log}); - // // vm.Output = alert.bind(window); -// this.vm.Output = this.log;//prompt.showToast; - let fsmname = 'Start.Main'; - let fsm = this.vm.CreateFSM(fsmname); - if (!fsm) { - this.log('no fsm'); - throw Error("No FSM named " + fsmname); + let obcanvas = new obcanvaslib.OBCanvas2D(stage); + // let ctx = stage.getContext('2d'); + // ctx.fillRect(15, 15, 50, 50); + + let nativeLibs = [obcanvas.install.bind(obcanvas)]; + let loader = obvm.OBScriptLoader; + let loadedScript = loader.loadScript(scriptArrayBuffer, nativeLibs); + this.vm = new obvm.OBVM(loadedScript,{setTimeout:setTimeout,Output:this.log}); + // // vm.Output = alert.bind(window); + // this.vm.Output = this.log;//prompt.showToast; + let fsmname = 'Start.Main'; + let fsm = this.vm.CreateFSM(fsmname); + if (!fsm) { + this.log('no fsm'); + throw Error("No FSM named " + fsmname); + } + this.fsm = fsm; + } catch (e) { + this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); + } finally { } - this.fsm = fsm; - } catch (e) { - this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); - } finally { - } + }); + }, + pageError(e){ + this.log(e.message); }, onActive() { setTimeout(()=>{ -- Gitee From 0d5cd88896eaad026c7983d99642259dfe456989 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Tue, 12 Apr 2022 12:31:44 +0800 Subject: [PATCH 26/30] =?UTF-8?q?=E8=A1=A5=E5=85=85=E5=BC=80=E6=BA=90?= =?UTF-8?q?=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- hap/entry/src/main/js/MainAbility/app.js | 5 + .../src/main/js/MainAbility/common/canvas.js | 138 +++++++++++------- .../common/component/ob_dynamic.js | 7 +- .../main/js/MainAbility/common/runtime/vm.js | 13 +- .../main/js/MainAbility/pages/index/index.js | 1 + .../main/js/MainAbility/pages/second/page.hml | 13 ++ .../main/js/MainAbility/pages/second/page.js | 7 +- .../js/MainAbility/pages/third/second.hml | 15 +- .../main/js/MainAbility/pages/third/second.js | 5 + 9 files changed, 144 insertions(+), 60 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/app.js b/hap/entry/src/main/js/MainAbility/app.js index 6d060ff..e244b5b 100644 --- a/hap/entry/src/main/js/MainAbility/app.js +++ b/hap/entry/src/main/js/MainAbility/app.js @@ -1,3 +1,8 @@ +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 + */ export default { onCreate() { console.info("Application onCreate"); diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index 4fdbc77..bb3627f 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -1,30 +1,31 @@ -/* - * Copyright (c) 2020-2021 Du Tian Wei - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 */ -export class OBCanvas2D { - /** - * @type {HTMLCanvasElement} - */ - canvas; - /** - * @type {CanvasRenderingContext2D} - */ - canvas2dctx; - /** - * - * @param {HTMLCanvasElement} canvas - */ +"use strict" + +// import * as util from '../runtime/util.js' +class Vector2 { + // x; y; + constructor(x, y) { + this.x = x; + this.y = y; + } +} +class OBCanvas2D { + // /** + // * @type {HTMLCanvasElement} + // */ + // canvas; + // /** + // * @type {CanvasRenderingContext2D} + // */ + // canvas2dctx; + // /** + // * + // * @param {HTMLCanvasElement} canvas + // */ constructor(canvas) { this.canvas = canvas; this.canvas2dctx = canvas.getContext('2d'); @@ -55,55 +56,80 @@ export class OBCanvas2D { } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.strokeStyle = str_color.substr(0, 7); + this.canvas2dctx.strokeStyle = str_color; } - getWidth(){ - return 750; + getVector2X(v) { + return v.x; } - getHeight(){ - return 1280; + getVector2Y(v) { + return v.y; } + // drawImage(imageName, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, st) { + // let vm = st.fsm.VM; + // let asset = vm.assets[imageName]; + // if (!asset) { + // console.warn('no asset named ' + imageName); + // return; + // } + // let img = asset.img; + // if (!img) { + // img = new Image(); + + // let base64 = util.arrayBufferToBase64(asset); + // let fileType = util.fileType(imageName).substring(1); + // img.src = 'data:image/' + fileType + ';base64,' + base64; + // asset.img = img; + // } + // if (sWidth > 0 && sHeight > 0) { + // this.canvas2dctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); + // } else if (dWidth > 0 && dHeight > 0) { + // this.canvas2dctx.drawImage(img, dx, dy, dWidth, dHeight); + // } else { + // this.canvas2dctx.drawImage(img, dx, dy); + // } + // } /** * 安装到脚本库 * @param {OBScript} script */ install(script) { - this.canvas2dctx.fillRect(50,50,50,50); script.InstallLib("canvas2d", "canvas2d", [ - script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'fillRect'), - script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'clearRect'), + script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), // canvas2dctx.fillStyle=color - script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister'],'setFillStyleColor'), - script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'strokeRect'), - script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister'],'fillText'), - script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), [],'beginPath'), - script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'arc'), - script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), [],'fill'), - script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), [],'closePath'), + script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'arcTo'), - script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'bezierCurveTo'), - script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister'],'moveTo'), - script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister'],'lineTo'), + script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister'],'ellipse'), - script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'],'rect'), - script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister'],'rotate'), - script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister'],'scale'), - script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister'],'setStrokeStyleColor'), - script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), [],'stroke'), + script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), -// script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), -// script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), - script.NativeUtil.closureReturnValue(this.getHeight.bind(this), 'LongRegister',[],'getHeight'), - script.NativeUtil.closureReturnValue(this.getWidth.bind(this), 'LongRegister',[],'getWidth'), + script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), script.NativeUtil.fieldSetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), + // script.NativeUtil.closureVoid(this.drawImage.bind(this), ['StringRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister'], true), ]); } -} \ No newline at end of file +} + +// module.exports = {OBCanvas2D}; +export { OBCanvas2D, Vector2 }; \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js b/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js index 19f1cef..1eeca36 100644 --- a/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js +++ b/hap/entry/src/main/js/MainAbility/common/component/ob_dynamic.js @@ -1,4 +1,9 @@ - +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 + */ + export default { props: { title: { diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 0f30d7a..4f66c1f 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -1529,8 +1529,19 @@ } let fsmdata = this.script.FullNameFSMData[name]; if (!fsmdata) { - return null; + for(let k in this.script.FullNameFSMData){ + if(k===name){ + fsmdata = this.script.FullNameFSMData[k]; + break; + } + } + if (!fsmdata) { + return null; + } } +// if (!fsmdata) { +// return null; +// } let uBFSM = new OBVMFSM(this, fsmdata); let list = this.Running[name]; if (!list) { diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index eb3c3cb..5c4ff73 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -135,6 +135,7 @@ export default { this.log('no fsm'); throw Error("No FSM named " + fsmname); } + this.log(fsmname + ' created'); this.fsm = fsm; } catch (e) { this.log("\nERROR:"+e.toString()+"\n" + JSON.stringify(e)); diff --git a/hap/entry/src/main/js/MainAbility/pages/second/page.hml b/hap/entry/src/main/js/MainAbility/pages/second/page.hml index 0a0d321..4d49397 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/page.hml +++ b/hap/entry/src/main/js/MainAbility/pages/second/page.hml @@ -1,3 +1,16 @@ +
diff --git a/hap/entry/src/main/js/MainAbility/pages/second/page.js b/hap/entry/src/main/js/MainAbility/pages/second/page.js index 67f72af..66ab504 100644 --- a/hap/entry/src/main/js/MainAbility/pages/second/page.js +++ b/hap/entry/src/main/js/MainAbility/pages/second/page.js @@ -1,4 +1,9 @@ -import router from '@system.router' +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 + */ + import router from '@system.router' import util from '@ohos.util' export default { diff --git a/hap/entry/src/main/js/MainAbility/pages/third/second.hml b/hap/entry/src/main/js/MainAbility/pages/third/second.hml index 0a0d321..9ed7aa6 100644 --- a/hap/entry/src/main/js/MainAbility/pages/third/second.hml +++ b/hap/entry/src/main/js/MainAbility/pages/third/second.hml @@ -1,4 +1,17 @@ -
+ +
{{info}} diff --git a/hap/entry/src/main/js/MainAbility/pages/third/second.js b/hap/entry/src/main/js/MainAbility/pages/third/second.js index 93a75dd..7773796 100644 --- a/hap/entry/src/main/js/MainAbility/pages/third/second.js +++ b/hap/entry/src/main/js/MainAbility/pages/third/second.js @@ -1,3 +1,8 @@ +/** + * @license + * Copyright 2021 Du Tian Wei + * SPDX-License-Identifier: Apache-2.0 + */ import router from '@system.router' import util from '@ohos.util' -- Gitee From 2988ad247a67afd542004ad1507b1e734c13473a Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sat, 16 Apr 2022 23:07:58 +0800 Subject: [PATCH 27/30] update runtime --- .../src/main/js/MainAbility/common/canvas.js | 298 ++++++++++-------- .../main/js/MainAbility/common/runtime/vm.js | 56 +++- .../main/js/MainAbility/pages/index/index.hml | 4 +- 3 files changed, 210 insertions(+), 148 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index bb3627f..d4554e7 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -3,133 +3,173 @@ * Copyright 2021 Du Tian Wei * SPDX-License-Identifier: Apache-2.0 */ -"use strict" + "use strict" -// import * as util from '../runtime/util.js' -class Vector2 { - // x; y; - constructor(x, y) { - this.x = x; - this.y = y; - } -} -class OBCanvas2D { - // /** - // * @type {HTMLCanvasElement} - // */ - // canvas; - // /** - // * @type {CanvasRenderingContext2D} - // */ - // canvas2dctx; - // /** - // * - // * @param {HTMLCanvasElement} canvas - // */ - constructor(canvas) { - this.canvas = canvas; - this.canvas2dctx = canvas.getContext('2d'); - } - /** - * - * @param {Number} color - */ - setFillStyleColor(color) { - let str_color; - if (color < 0) { - str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) - str_color = '#' + str_color; - } else { - str_color = '#' + color.toString(16).padStart(8, '0'); - } - this.canvas2dctx.fillStyle = str_color.substr(0, 7); - } - /** - * - * @param {Number} color - */ - setStrokeStyleColor(color) { - let str_color; - if (color < 0) { - str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) - str_color = '#' + str_color; - } else { - str_color = '#' + color.toString(16).padStart(8, '0'); - } - this.canvas2dctx.strokeStyle = str_color; - } - getVector2X(v) { - return v.x; - } - getVector2Y(v) { - return v.y; - } - // drawImage(imageName, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, st) { - // let vm = st.fsm.VM; - // let asset = vm.assets[imageName]; - // if (!asset) { - // console.warn('no asset named ' + imageName); - // return; - // } - // let img = asset.img; - // if (!img) { - // img = new Image(); - - // let base64 = util.arrayBufferToBase64(asset); - // let fileType = util.fileType(imageName).substring(1); - // img.src = 'data:image/' + fileType + ';base64,' + base64; - // asset.img = img; - // } - // if (sWidth > 0 && sHeight > 0) { - // this.canvas2dctx.drawImage(img, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); - // } else if (dWidth > 0 && dHeight > 0) { - // this.canvas2dctx.drawImage(img, dx, dy, dWidth, dHeight); - // } else { - // this.canvas2dctx.drawImage(img, dx, dy); - // } - // } - /** - * 安装到脚本库 - * @param {OBScript} script - */ - install(script) { - script.InstallLib("canvas2d", "canvas2d", [ - script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - // canvas2dctx.fillStyle=color - script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), - script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), - script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), - script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this), ['DoubleRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this), ['DoubleRegister', 'DoubleRegister']), - script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), - script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), - script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), - script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), - script.NativeUtil.fieldSetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), - script.NativeUtil.fieldGetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), - // script.NativeUtil.closureVoid(this.drawImage.bind(this), ['StringRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister', 'LongRegister'], true), - ]); - } -} - -// module.exports = {OBCanvas2D}; -export { OBCanvas2D, Vector2 }; \ No newline at end of file + class Vector2 { + // x; y; + constructor(x, y) { + this.x = x; + this.y = y; + } + } + class OBCanvas2D { + // /** + // * @type {HTMLCanvasElement} + // */ + // canvas; + // /** + // * @type {CanvasRenderingContext2D} + // */ + // canvas2dctx; + // /** + // * + // * @param {HTMLCanvasElement} canvas + // */ + constructor(canvas) { + this.canvas = canvas; + this.canvas2dctx = canvas.getContext('2d'); + } + /** + * + * @param {Number} color + */ + setFillStyleColor(color) { + let str_color; + if (color < 0) { + str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) + str_color = '#' + str_color; + } else { + str_color = '#' + color.toString(16).padStart(8, '0'); + } + this.canvas2dctx.fillStyle = str_color.substr(0, 7); + } + /** + * + * @param {Number} color + */ + setStrokeStyleColor(color) { + let str_color; + if (color < 0) { + str_color = (Number.MAX_SAFE_INTEGER + color + 1).toString(16).substr(-8) + str_color = '#' + str_color; + } else { + str_color = '#' + color.toString(16).padStart(8, '0'); + } + this.canvas2dctx.strokeStyle = str_color; + } + getVector2X(v) { + return v.x; + } + getVector2Y(v) { + return v.y; + } + drawImage8arg(imageName, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight, st) { + let vm = st.fsm.VM; + let asset = vm.assets[imageName]; + if (!asset) { + console.warn('no asset named ' + imageName); + return; + } + let rx = dWidth < 0; + if (rx) { + dx = -dx; + } + let ry = dHeight < 0; + if (ry) { + dy = -dy; + } + if (rx || ry) { + this.canvas2dctx.save(); + this.canvas2dctx.scale(rx ? -1 : 1, ry ? -1 : 1); + } + this.canvas2dctx.drawImage(asset, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); + if (rx || ry) { + this.canvas2dctx.restore(); + } + } + drawImage4arg(imageName, dx, dy, dWidth, dHeight, st) { + let vm = st.fsm.VM; + let asset = vm.assets[imageName]; + if (!asset) { + console.warn('no asset named ' + imageName); + return; + } + this.drawImage8arg(imageName, 0, 0, asset.width, asset.height, dx, dy, dWidth, dHeight, st); + } + drawImage2arg(imageName, dx, dy, st) { + let vm = st.fsm.VM; + let asset = vm.assets[imageName]; + if (!asset) { + console.warn('no asset named ' + imageName); + return; + } + + this.drawImage4arg(imageName, dx, dy, asset.width, asset.height, st); + } + imageWidth(imageName, st) { + let vm = st.fsm.VM; + let asset = vm.assets[imageName]; + if (!asset) { + console.warn('no asset named ' + imageName); + return 0; + } + return asset.width; + } + imageHeight(imageName, st) { + let vm = st.fsm.VM; + let asset = vm.assets[imageName]; + if (!asset) { + console.warn('no asset named ' + imageName); + return 0; + } + return asset.height; + } + /** + * 安装到脚本库 + * @param {OBScript} script + */ + install(script) { + script.InstallLib("canvas2d", "canvas2d", [ + script.NativeUtil.closureVoid(this.canvas2dctx.fillRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.clearRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + // canvas2dctx.fillStyle=color + script.NativeUtil.closureVoid(this.setFillStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.strokeRect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fillText.bind(this.canvas2dctx), ['StringRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.beginPath.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.arc.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.fill.bind(this.canvas2dctx), []), + script.NativeUtil.closureVoid(this.canvas2dctx.closePath.bind(this.canvas2dctx), []), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'font', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.arcTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.bezierCurveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.moveTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.lineTo.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textAlign', 'StringRegister'), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'textBaseline', 'StringRegister'), + script.NativeUtil.closureVoid(this.canvas2dctx.ellipse.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rect.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.rotate.bind(this.canvas2dctx), ['DoubleRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.scale.bind(this.canvas2dctx), ['DoubleRegister', 'DoubleRegister']), + script.NativeUtil.closureVoid(this.setStrokeStyleColor.bind(this), ['LongRegister']), + script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), + script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), + script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), + script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), + script.NativeUtil.fieldSetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), + script.NativeUtil.fieldGetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), + script.NativeUtil.closureVoid(this.drawImage8arg.bind(this), ['StringRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'], true), + script.NativeUtil.closureVoid(this.drawImage4arg.bind(this), ['StringRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'], true), + script.NativeUtil.closureVoid(this.drawImage2arg.bind(this), ['StringRegister', 'DoubleRegister', 'DoubleRegister'], true), + script.NativeUtil.closureReturnValue(this.imageWidth.bind(this), 'DoubleRegister', ['StringRegister'], true), + script.NativeUtil.closureReturnValue(this.imageHeight.bind(this), 'DoubleRegister', ['StringRegister'], true), + ]); + } + } + + // module.exports = {OBCanvas2D}; + export { OBCanvas2D, Vector2 }; \ No newline at end of file diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 4f66c1f..cb0fea8 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -80,7 +80,7 @@ * @param {Number[]} argtype * @returns */ - static closureReturnValue(func, retRegisterType, argtype) { + static closureReturnValue(func, retRegisterType, argtype, addVMarg) { /** * * @param {OBFunctionBuilder} builder @@ -101,6 +101,11 @@ }); builder[retRegisterType][retRegIdx] = ((st, f, local) => { let argVals = argGetters.map(g => g(st, f, local)); + if (addVMarg) { + argVals.push(st); + argVals.push(f); + argVals.push(local); + } return func.apply(null, argVals); }); }; @@ -404,6 +409,8 @@ return new COND(); case 59: return new NEW(); + case 60: + return new CSTR(); default: throw Error("Unknown byte code command:" + cmd); } @@ -1409,7 +1416,12 @@ let utf8decoder = new util.TextDecoder("utf-8", { fatal: true }); - str = utf8decoder.decode(ui8); + try { + str = utf8decoder.decode(ui8); + } catch (e) { + console.warn(e); + str = ""; + } if (str === null) { throw Error('no string value of idx:' + stringIdx); } @@ -1529,19 +1541,8 @@ } let fsmdata = this.script.FullNameFSMData[name]; if (!fsmdata) { - for(let k in this.script.FullNameFSMData){ - if(k===name){ - fsmdata = this.script.FullNameFSMData[k]; - break; - } - } - if (!fsmdata) { - return null; - } + return null; } -// if (!fsmdata) { -// return null; -// } let uBFSM = new OBVMFSM(this, fsmdata); let list = this.Running[name]; if (!list) { @@ -2170,8 +2171,6 @@ state.HandleMessage(this); } catch (err) { if (!(err instanceof VMInterruptException)) { - state.fsm.VM.Output(err); - state.fsm.VM.Output(err.stack); console.error(err); throw err; } @@ -4228,7 +4227,7 @@ } } /** - * value of may by key + * value of map by key */ class VOM extends OBInstruction { // map; @@ -4416,6 +4415,29 @@ } } + export class CSTR extends OBInstruction { + + init(code, builder, instructions, i) { + this.maxi = code & 0x3f; + this.mini = (code >> 6) & 0x3f; + this.valuei = (code >> 12) & 0x3f; + this.reti = (code >> 18) & 0x3f; + } + + link(builder, instructions, idx) { + let maxr = builder.DoubleRegister[this.maxi]; + let minr = builder.DoubleRegister[this.mini]; + let valuer = builder.DoubleRegister[this.valuei]; + builder.DoubleRegister[this.reti] = (st, f, l) => { + let v = valuer(st, f, l); + let max = maxr(st, f, l); + let min = minr(st, f, l); + return Math.min(Math.max(v, min), max); + }; + } + + } + export class OBStructDataSerializer { relocation = new Relocation(); /** diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.hml b/hap/entry/src/main/js/MainAbility/pages/index/index.hml index 2c76483..789d88e 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.hml +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.hml @@ -19,7 +19,7 @@ -->
-
+
{{ info }}
@@ -30,7 +30,7 @@ ontouchmove="ob_touchmove" ontouchcancel="ob_touchcancel" ontouchend="ob_touchend" onlongpress="ob_longpress" onclick="ob_click"> - +
\ No newline at end of file -- Gitee From 4cd0db271b614419d27b0d33ad4bee20d6d46944 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sun, 17 Apr 2022 06:57:42 +0800 Subject: [PATCH 28/30] =?UTF-8?q?=E6=9F=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ .../src/main/js/MainAbility/common/canvas.js | 12 ++++++++++-- .../src/main/js/MainAbility/common/runtime/vm.js | 14 +++++++++++--- .../src/main/js/MainAbility/pages/index/index.js | 15 ++++++++------- 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index f98281f..0cc1db4 100644 --- a/README.md +++ b/README.md @@ -28,3 +28,7 @@ DEMO: * 邮件列表: 暂无 +hdc_std.exe file send main.xe /data/accounts/account_0/appdata/com.openblock.ohos/com.openblock.ohos/com.openblock.ohos.MainAbility/main.xe + +chmod 777 main.xe + diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index d4554e7..55e880a 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -124,6 +124,12 @@ } return asset.height; } + canvasWidth(){ + return 750;//this.canvas.getBoundingClientRect().width; + } + canvasHeight(){ + return 1280;//this.canvas.getBoundingClientRect().height; + } /** * 安装到脚本库 * @param {OBScript} script @@ -158,8 +164,10 @@ script.NativeUtil.closureVoid(this.canvas2dctx.stroke.bind(this.canvas2dctx), []), script.NativeUtil.objFieldGetter('x', 'DoubleRegister'), script.NativeUtil.objFieldGetter('y', 'DoubleRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), - script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), +// script.NativeUtil.fieldGetter(this.canvas, 'height', 'LongRegister'), +// script.NativeUtil.fieldGetter(this.canvas, 'width', 'LongRegister'), + script.NativeUtil.closureReturnValue(this.canvasHeight.bind(this), 'LongRegister', []), + script.NativeUtil.closureReturnValue(this.canvasWidth.bind(this), 'LongRegister', []), script.NativeUtil.fieldSetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), script.NativeUtil.fieldGetter(this.canvas2dctx, 'lineWidth', 'DoubleRegister'), script.NativeUtil.closureVoid(this.drawImage8arg.bind(this), ['StringRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister', 'DoubleRegister'], true), diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index cb0fea8..228e6f4 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -1856,16 +1856,21 @@ HandleMessage(m) { this.currentMessage = m; + let mname = m.name; try { let typeName = null; if (m.arg != null) { typeName = m.GetArgType(); } - let hl = this.data.MessageHandlers[m.name]; + this.fsm.VM.Log(mname+'/'+typeName); + let hl = this.data.MessageHandlers[mname]; if (hl) { hl.forEach(h => { - if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { + let hArgTypeName = h.ArgTypeName; + if (hArgTypeName === "" || hArgTypeName === typeName) { new OBVMFunction(h.Func).Call(this); + }else{ + this.fsm.VM.Log('skip '+mname+'/'+typeName +':'+hArgTypeName); } }); } @@ -2172,6 +2177,7 @@ } catch (err) { if (!(err instanceof VMInterruptException)) { console.error(err); + state.fsm.VM.Log(err) throw err; } } @@ -3150,7 +3156,9 @@ } else { typename = OBMessage.ArgTypeOf(this.BodyTypeID, body); } - fsm.PostMessage(new OBUserMessage(title, typename, body, st.fsm)); + let msg = new OBUserMessage(title, typename, body, st.fsm) + st.fsm.VM.Log('sendMsg '+title+'/'+typename); + fsm.PostMessage(msg); } return ++pos; }); diff --git a/hap/entry/src/main/js/MainAbility/pages/index/index.js b/hap/entry/src/main/js/MainAbility/pages/index/index.js index 5c4ff73..87a2212 100644 --- a/hap/entry/src/main/js/MainAbility/pages/index/index.js +++ b/hap/entry/src/main/js/MainAbility/pages/index/index.js @@ -104,16 +104,16 @@ export default { var context = featureAbility.getContext(); context.getOrCreateLocalDir().then((dir) => { - this.log("root dir=" + dir); +// this.log("root dir=" + dir); let stage = this.$refs.canvas1; try { - console.log('openblock 中文'+'测试'); +// console.log('openblock 中文'+'测试'); // /storage/media/100/local/files filepath = dir + "/main.xe";//"/data/"+app.getInfo().appID+"/main.xe"; - this.log(filepath); - stage.width = stage.width; +// this.log(filepath); +// stage.width = stage.width; let fd = fileio.openSync(filepath, 0o2); let st = fileio.fstatSync(fd); let scriptArrayBuffer = new ArrayBuffer(st.size); @@ -152,14 +152,15 @@ export default { this.uninited = false; this.initStage(); } - this.updateInterval = setInterval(this.update, 3000); + this.updateInterval = setInterval(this.update, 5000); this.fileCheckInterval = setInterval(this.checkFile, 3000); },1); }, checkFile() { - let fd = fileio.openSync(filepath, 0o2); - let stat = fileio.fstatSync(fd); +// let fd = fileio.openSync(filepath, 0o2); + let stat = fileio.statSync(filepath); let ctime = stat.ctime; +// fileio.closeSync(fd); if (this.filectime == -1) { this.filectime = ctime; } else if (this.filectime != ctime) { -- Gitee From 8d174284c8debfde8f8a24e1d3b35039bb331b26 Mon Sep 17 00:00:00 2001 From: duzc2 Date: Sat, 23 Apr 2022 01:04:00 +0800 Subject: [PATCH 29/30] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20fieldGetter=20?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E9=94=99=E8=AF=AF=E5=AF=84=E5=AD=98=E5=99=A8?= =?UTF-8?q?=E7=9A=84bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/js/MainAbility/common/runtime/vm.js | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js index 228e6f4..4589daf 100644 --- a/hap/entry/src/main/js/MainAbility/common/runtime/vm.js +++ b/hap/entry/src/main/js/MainAbility/common/runtime/vm.js @@ -21,7 +21,7 @@ } static fieldGetter(target, fieldName, register) { return (builder, args) => { - builder[register][args[1] & 0xfff] = (st, f, local) => { + builder[register][args[0] & 0xfff] = (st, f, local) => { return target[fieldName]; }; }; @@ -1416,12 +1416,7 @@ let utf8decoder = new util.TextDecoder("utf-8", { fatal: true }); - try { - str = utf8decoder.decode(ui8); - } catch (e) { - console.warn(e); - str = ""; - } + str = utf8decoder.decode(ui8); if (str === null) { throw Error('no string value of idx:' + stringIdx); } @@ -1856,21 +1851,16 @@ HandleMessage(m) { this.currentMessage = m; - let mname = m.name; try { let typeName = null; if (m.arg != null) { typeName = m.GetArgType(); } - this.fsm.VM.Log(mname+'/'+typeName); - let hl = this.data.MessageHandlers[mname]; + let hl = this.data.MessageHandlers[m.name]; if (hl) { hl.forEach(h => { - let hArgTypeName = h.ArgTypeName; - if (hArgTypeName === "" || hArgTypeName === typeName) { + if (h.ArgTypeName === "" || h.ArgTypeName === typeName) { new OBVMFunction(h.Func).Call(this); - }else{ - this.fsm.VM.Log('skip '+mname+'/'+typeName +':'+hArgTypeName); } }); } @@ -2177,7 +2167,6 @@ } catch (err) { if (!(err instanceof VMInterruptException)) { console.error(err); - state.fsm.VM.Log(err) throw err; } } @@ -3156,9 +3145,7 @@ } else { typename = OBMessage.ArgTypeOf(this.BodyTypeID, body); } - let msg = new OBUserMessage(title, typename, body, st.fsm) - st.fsm.VM.Log('sendMsg '+title+'/'+typename); - fsm.PostMessage(msg); + fsm.PostMessage(new OBUserMessage(title, typename, body, st.fsm)); } return ++pos; }); -- Gitee From db394893029d43604bdcd8c4b37c9c6aa6c7826a Mon Sep 17 00:00:00 2001 From: duzc2 Date: Wed, 4 May 2022 23:36:52 +0800 Subject: [PATCH 30/30] =?UTF-8?q?canvas=20=E9=A2=9C=E8=89=B2=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: duzc2 --- .../src/main/js/MainAbility/common/canvas.js | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/hap/entry/src/main/js/MainAbility/common/canvas.js b/hap/entry/src/main/js/MainAbility/common/canvas.js index 55e880a..6ca1c7d 100644 --- a/hap/entry/src/main/js/MainAbility/common/canvas.js +++ b/hap/entry/src/main/js/MainAbility/common/canvas.js @@ -30,9 +30,9 @@ this.canvas2dctx = canvas.getContext('2d'); } /** - * - * @param {Number} color - */ + * + * @param {Number} color + */ setFillStyleColor(color) { let str_color; if (color < 0) { @@ -41,12 +41,14 @@ } else { str_color = '#' + color.toString(16).padStart(8, '0'); } - this.canvas2dctx.fillStyle = str_color.substr(0, 7); + str_color = "#" + str_color.substring(7) + str_color.substring(1,7); + console.log(str_color); + this.canvas2dctx.fillStyle = str_color; } /** - * - * @param {Number} color - */ + * + * @param {Number} color + */ setStrokeStyleColor(color) { let str_color; if (color < 0) { @@ -55,6 +57,8 @@ } else { str_color = '#' + color.toString(16).padStart(8, '0'); } + str_color = "#" + str_color.substring(7) + str_color.substring(1,7); + console.log(str_color); this.canvas2dctx.strokeStyle = str_color; } getVector2X(v) { -- Gitee