From 053ea0992846fd69fe94b352d281be8b3e2ade1d Mon Sep 17 00:00:00 2001 From: fy Date: Fri, 3 Nov 2023 00:52:12 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20jsport=E7=BC=96=E8=AF=91=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E4=BF=AE=E6=94=B9=E4=B8=BAesm=E5=B9=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E8=87=B3npm=EF=BC=8C=E5=8C=85=E5=90=8Ddicescript?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/jsport.yml | 5 +- jsport/.npmignore | 7 ++ jsport/index.d.ts | 176 +++++++++++++++++++++++++++++++++++ jsport/index.html | 123 +++++++++++++----------- jsport/index.js | 3 + jsport/main.go | 67 +++++++------ jsport/package.json | 13 ++- jsport/webpack.config.js | 16 ++++ types.go | 4 + 9 files changed, 325 insertions(+), 89 deletions(-) create mode 100644 jsport/.npmignore create mode 100644 jsport/index.d.ts create mode 100644 jsport/index.js create mode 100644 jsport/webpack.config.js diff --git a/.github/workflows/jsport.yml b/.github/workflows/jsport.yml index d015d670..569c295c 100644 --- a/.github/workflows/jsport.yml +++ b/.github/workflows/jsport.yml @@ -30,7 +30,10 @@ jobs: run: peg -switch -inline roll.peg - name: Build - run: gopherjs build github.com/sealdice/dicescript/jsport -o jsport/dicescript.js + run: gopherjs build github.com/sealdice/dicescript/jsport -o jsport/dicescript.cjs + + - name: Bundle ESM + run: cd ./jsport && yarn && yarn build - name: Deploy uses: peaceiris/actions-gh-pages@v3 diff --git a/jsport/.npmignore b/jsport/.npmignore new file mode 100644 index 00000000..210a48d0 --- /dev/null +++ b/jsport/.npmignore @@ -0,0 +1,7 @@ +node_modules +dicescript.cjs +dicescript.cjs.map +index.html +main.go +index.js +webpack.config.js diff --git a/jsport/index.d.ts b/jsport/index.d.ts new file mode 100644 index 00000000..8f784b20 --- /dev/null +++ b/jsport/index.d.ts @@ -0,0 +1,176 @@ +export declare function newVM(): DiceScriptContext; +export declare function newVMForPlaygournd(): DiceScriptContext; +export declare const help: string; + +export declare function vmNewDict(): VMValue; +export declare function vmNewFloat(): VMValue; +export declare function vmNewInt(): VMValue; +export declare function vmNewStr(): VMValue; +export declare function newValueMap(): ValueMap; +export declare function newConfig(): RollConfig; + +declare interface GoError { + $type: 'errors.*error'; + /** error info */ + Error(): string; +} + +declare interface ValueMap { + $type: 'github.com/sealdice/dicescript.*ValueMap'; + + Load(key: string): [VMValue | null, boolean]; + MustLoad(key: string): VMValue | null; + Store(key: string, value: VMValue): void; + LoadOrStore(key: string, value: VMValue): [VMValue, boolean]; + LoadAndDelete(key: string): [VMValue | null, boolean]; + Delete(key: string): void; + Range(f: (key: string, value: VMValue) => boolean): void; + + __internal_object__: { + $val: any; + mu: any; + read: any; + dirty: boolean; + misses: number; + }; +} + +declare interface VMValue { + $type: 'github.com/sealdice/dicescript.*VMValue'; + + ToJSONRaw(save: Map): [Uint8Array, GoError]; + ToJSON(): [Uint8Array, GoError]; + UnmarshalJSON(input: Uint8Array): GoError; + ArrayItemGet(ctx: DiceScriptContext, index: number): VMValue | null; + ArrayItemSet(ctx: DiceScriptContext, index: number, val: VMValue): boolean; + ArrayFuncKeepBase(ctx: DiceScriptContext, pickNum: number, orderType: number): [boolean, number]; + ArrayFuncKeepHigh(ctx: DiceScriptContext, pickNum: number): [boolean, number]; + ArrayFuncKeepLow(ctx: DiceScriptContext, pickNum: number): [boolean, number]; + Clone(): VMValue; + AsBool(): boolean; + ToString(): string; + // toStringRaw(ri: recursionInfo): string; + // toReprRaw(ri: recursionInfo): string; + ToRepr(): string; + ReadInt(): [number, boolean]; + ReadFloat(): [number, boolean]; + ReadString(): [string, boolean]; + // ReadArray(): [ArrayData, boolean]; + // ReadComputed(): [ComputedData, boolean]; + // ReadDictData(): [DictData, boolean]; + // MustReadDictData(): DictData; + // MustReadArray(): ArrayData; + MustReadInt(): number; + MustReadFloat(): number; + // ReadFunctionData(): [FunctionData, boolean]; + // ReadNativeFunctionData(): [NativeFunctionData, boolean]; + // ReadNativeObjectData(): [NativeObjectData, boolean]; + OpAdd(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpSub(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpMultiply(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpDivide(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpModulus(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpPower(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpNullCoalescing(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpCompLT(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpCompLE(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpCompEQ(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpCompNE(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpCompGE(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpCompGT(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpBitwiseAnd(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpBitwiseOr(ctx: DiceScriptContext, v2: VMValue): VMValue; + OpPositive(): VMValue; + OpNegation(): VMValue; + AttrSet(ctx: DiceScriptContext, name: string, val: VMValue): VMValue; + AttrGet(ctx: DiceScriptContext, name: string): VMValue; + ItemGet(ctx: DiceScriptContext, index: VMValue): VMValue; + ItemSet(ctx: DiceScriptContext, index: VMValue, val: VMValue): boolean; + GetSlice(ctx: DiceScriptContext, a: number, b: number, step: number): VMValue; + Length(ctx: DiceScriptContext): number; + GetSliceEx(ctx: DiceScriptContext, a: VMValue, b: VMValue): VMValue; + SetSlice(ctx: DiceScriptContext, a: number, b: number, step: number, val: VMValue): boolean; + SetSliceEx(ctx: DiceScriptContext, a: VMValue, b: VMValue, val: VMValue): boolean; + ArrayRepeatTimesEx(ctx: DiceScriptContext, times: VMValue): VMValue; + GetTypeName(): string; + ComputedExecute(ctx: DiceScriptContext): VMValue; + FuncInvoke(ctx: DiceScriptContext, params: VMValue[]): VMValue; + FuncInvokeNative(ctx: DiceScriptContext, params: VMValue[]): VMValue; + AsDictKey(): [string, GoError]; + + __internal_object__: { + $val: any, + TypeId: any, + Value: any + }; +} + +declare interface RollConfig { + EnableDiceWoD: boolean; + EnableDiceCoC: boolean; + EnableDiceFate: boolean; + EnableDiceDoubleCross: boolean; + + DisableBitwiseOp: boolean; + DisableStmts: boolean; + DisableNDice: boolean; + + CallbackLoadVar: (name: string) => [string, VMValue]; + CallbackSt: (type: string, name: string, val: VMValue, extra: VMValue, op: string, detail: string) => void; + + OpCountLimit: number; + DefaultDiceSideExpr: string; + defaultDiceSideExprCacheFunc: VMValue; + + PrintBytecode: boolean; + IgnoreDiv0: boolean; + + DiceMinMode: boolean; + DiceMaxMode: boolean; +} + + +export declare interface DiceScriptContext { + $type: 'github.com/sealdice/dicescript.*Context'; + + RunExpr(value: string): VMValue | undefined; + /** Eval a code, store result in ctx.Ret, store error in ctx.Error */ + Run(expr: string): void; + GetAsmText(): string; + StackTop(): number; + Depth(): number; + Init(): void; + SetConfig(cfg: RollConfig); + loadInnerVar(name: string): VMValue | undefined; + LoadNameGlobal(name: string, isRaw: boolean): VMValue | undefined; + LoadNameLocal(name: string, isRaw: boolean): VMValue | undefined; + LoadName(name: string, isRaw: boolean): VMValue | undefined; + StoreName(name: string, v: VMValue): void; + StoreNameLocal(name: string, v: VMValue): void; + StoreNameGlobal(name: string, v: VMValue): void; + + stack: VMValue[]; + top: number; + NumOpCount: number; + Error: GoError; + Ret: VMValue | null; + RestInput: string; + Matched: string; + Detail: string; + IsRunning: boolean; + readonly Config: RollConfig; + // flagsStack: RollConfig[]; + // CustomDiceInfo: customDiceItem[]; + ValueStoreHookFunc: (ctx: DiceScriptContext, name: string, v: VMValue) => boolean; + globalNames: ValueMap; + GlobalValueStoreFunc: (name: string, v: VMValue) => void; + GlobalValueLoadFunc: (name: string) => VMValue; + + __internal_object__: { + $val: any; + parser: any; + subThreadDepth: number; + attrs: any; + upCtx: any; + }; +} diff --git a/jsport/index.html b/jsport/index.html index 68a839d3..5b8f6598 100644 --- a/jsport/index.html +++ b/jsport/index.html @@ -1,78 +1,91 @@ + - - DiceScript 测试页 - + + DiceScript 测试页 + + - - - - + + + + -
+
-
{{i}}
+
{{i}}
-
- -
- +
+ +
+
-
提示: 还在开发中,支持语法详情看语法指南
-
控制台里有上一条指令的字节码。建议多ctrl+f5以免遇到旧版
-
有一个人物卡变量叫player,通过"_测试30"这种形式可以读取出数字30,可用于ra判定
+
提示: 还在开发中,支持语法详情看语法指南 +
+
控制台里有上一条指令的字节码。建议多ctrl+f5以免遇到旧版
+
有一个人物卡变量叫player,通过"_测试30"这种形式可以读取出数字30,可用于ra判定
-
+
- + - + + \ No newline at end of file diff --git a/jsport/index.js b/jsport/index.js new file mode 100644 index 00000000..5e04a776 --- /dev/null +++ b/jsport/index.js @@ -0,0 +1,3 @@ +import { ds } from './dicescript.cjs'; + +export default ds; diff --git a/jsport/main.go b/jsport/main.go index 077db68f..ef8e5b74 100644 --- a/jsport/main.go +++ b/jsport/main.go @@ -5,31 +5,32 @@ package main import ( "github.com/gopherjs/gopherjs/js" - dice "github.com/sealdice/dicescript" "regexp" "strconv" + + ds "github.com/sealdice/dicescript" ) -var scope = map[string]*dice.VMValue{} +var scope = map[string]*ds.VMValue{} func newVM(name string) *js.Object { - player := dice.VMValueNewDict(nil) - player.Store("力量", dice.VMValueNewInt(50)) - player.Store("敏捷", dice.VMValueNewInt(60)) - player.Store("智力", dice.VMValueNewInt(70)) + player := ds.VMValueNewDict(nil) + player.Store("力量", ds.VMValueNewInt(50)) + player.Store("敏捷", ds.VMValueNewInt(60)) + player.Store("智力", ds.VMValueNewInt(70)) scope["player"] = player.V() - vm := dice.NewVM() - //vm.GlobalValueStoreFunc = func(name string, v *dice.VMValue) { + vm := ds.NewVM() + //vm.GlobalValueStoreFunc = func(name string, v *ds.VMValue) { // scope[name] = v //} re := regexp.MustCompile(`^_(\D+)(\d+)$`) - vm.GlobalValueLoadFunc = func(name string) *dice.VMValue { + vm.GlobalValueLoadFunc = func(name string) *ds.VMValue { m := re.FindStringSubmatch(name) if len(m) > 1 { val, _ := strconv.ParseInt(m[2], 10, 64) - return dice.VMValueNewInt(val) + return ds.VMValueNewInt(val) } if v, exists := player.Load(name); exists { @@ -46,25 +47,33 @@ func newVM(name string) *js.Object { } func main() { - newDict := func() *dice.VMDictValue { - return dice.VMValueNewDict(nil) - } - - newValueMap := func() *dice.ValueMap { - return &dice.ValueMap{} - } - - js.Global.Set("dice", map[string]interface{}{ - "newVM": newVM, - "newValueMap": newValueMap, - "vmNewInt64": js.MakeWrapper(dice.VMValueNewInt), - "vmNewFloat64": js.MakeWrapper(dice.VMValueNewFloat), - "vmNewStr": js.MakeWrapper(dice.VMValueNewStr), + diceModule := map[string]interface{}{ + "newVMForPlaygournd": newVM, + "newVM": func() *js.Object { + vm := ds.NewVM() + return js.MakeFullWrapper(vm) + }, + "newConfig": func() *js.Object { + return js.MakeFullWrapper(&ds.RollConfig{}) + }, + "newValueMap": func() *js.Object { + return js.MakeFullWrapper(&ds.ValueMap{}) + }, + "vmNewInt": func(i int64) *js.Object { + return js.MakeFullWrapper(ds.VMValueNewInt(i)) + }, + "vmNewFloat": func(i float64) *js.Object { + return js.MakeFullWrapper(ds.VMValueNewFloat(i)) + }, + "vmNewStr": func(s string) *js.Object { + return js.MakeFullWrapper(ds.VMValueNewStr(s)) + }, //"vmNewArray": js.MakeWrapper(newArray), - "vmNewDict": js.MakeWrapper(newDict), - "help": js.MakeWrapper("此项目的js绑定: https://github.com/sealdice/dice"), - }) + "vmNewDict": func() *js.Object { + return js.MakeFullWrapper(ds.VMValueNewDict(nil)) + }, + "help": "此项目的js绑定: https://github.com/sealdice/dice", + } - //js.Module.Set("newVM", dice.NewVM) - //js.Module.Set("Context", dice.Context{}) + js.Module.Get("exports").Set("ds", diceModule) } diff --git a/jsport/package.json b/jsport/package.json index c8017acb..87174a16 100644 --- a/jsport/package.json +++ b/jsport/package.json @@ -1,10 +1,11 @@ { "name": "dicescript", - "version": "0.1.0", + "version": "0.1.2", "description": "Simple script language for TRPG dice engine.", - "main": "dicescript.js", + "module": "./dist/main.mjs", + "type": "module", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "build": "webpack ." }, "repository": { "type": "git", @@ -19,5 +20,9 @@ "bugs": { "url": "https://github.com/sealdice/dicescript/issues" }, - "homepage": "https://github.com/sealdice/dicescript#readme" + "homepage": "https://github.com/sealdice/dicescript#readme", + "devDependencies": { + "webpack": "^5.89.0", + "webpack-cli": "^5.1.4" + } } diff --git a/jsport/webpack.config.js b/jsport/webpack.config.js new file mode 100644 index 00000000..53c403c4 --- /dev/null +++ b/jsport/webpack.config.js @@ -0,0 +1,16 @@ +export default { + // … + experiments: { + outputModule: true, + }, + output: { + library: { + // do not specify a `name` here + type: 'module', + }, + }, + // mode: 'development', + // optimization: { + // usedExports: true, + // }, +}; diff --git a/types.go b/types.go index 00e61e46..705b7128 100644 --- a/types.go +++ b/types.go @@ -144,6 +144,10 @@ func (e *Context) Depth() int { return e.subThreadDepth } +func (e *Context) SetConfig(cfg *RollConfig) { + e.Config = *cfg +} + func (e *Context) Init() { e.attrs = &ValueMap{} e.globalNames = &ValueMap{}