From dfbe1d25539063b29c585f16bb0f70628232045d Mon Sep 17 00:00:00 2001 From: WolfGangS Date: Thu, 13 Nov 2025 19:24:17 +0000 Subject: [PATCH] builtins --- .github/workflows/release.yml | 6 +- deno.jsonc | 7 +- src/lsl/lsl-builtins.ts | 173 ++++++++++++++++++++++++++++++++++ src/main.ts | 9 ++ 4 files changed, 189 insertions(+), 6 deletions(-) create mode 100644 src/lsl/lsl-builtins.ts diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 79f1b61..ba233c4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -41,10 +41,6 @@ jobs: uses: actions/upload-pages-artifact@v3 with: path: docs/html/ - - uses: actions/upload-artifact@v4 - with: - name: keywords - path: data/keywords_lsl_formatted.llsd.xml - name: Hash run: sha1sum dist/* | sha1sum | cut -d " " -f 1 - name: Converts Markdown to HTML @@ -62,7 +58,7 @@ jobs: id: create_release uses: ncipollo/release-action@v1 with: - artifacts: sl_lua_types.zip, dist/*.json, dist/*.toml, dist/*.luau, dist/*.yml, dist/*.code-snippets + artifacts: sl_lua_types.zip, dist/*.json, dist/*.toml, dist/*.luau, dist/*.yml, dist/*.code-snippets. dist/*.txt deploy-pages: if: ${{ startsWith(github.ref, 'refs/tags/v') }} diff --git a/deno.jsonc b/deno.jsonc index afbd80c..636d379 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -2,7 +2,7 @@ "tasks": { // build "build": { - "dependencies": ["build-lsp","build-selene","build-json","build-vsc"] + "dependencies": ["build-lsp","build-selene","build-json","build-vsc","build-builtins"] }, "markdown": { "command": "cp -R dist docs/html/dist", @@ -18,6 +18,9 @@ "build-json" : { "dependencies": ["gen-json-slua", "gen-json-lsl"] }, + "build-builtins" : { + "dependencies": ["gen-builtins-lsl"] + }, "build-vsc" : { "dependencies": ["gen-vsc-snippets"] }, @@ -34,6 +37,8 @@ "gen-vsc-snippets": "deno -R -E src/main.ts data/lsl_definitions.yaml slua-vsc-snippets > dist/slua.code-snippets", // Generate Markdown "gen-markdown": "deno run -R -W -E src/main.ts ./data/lsl_definitions.yaml slua-markdown docs/output docs/html", + // Generate Builtins + "gen-builtins-lsl" : "deno run -R -W -E src/main.ts ./data/lsl_definitions.yaml lsl-builtins > dist/builtins.txt", // build and install "install": "deno task build && deno task copy-to-install", "copy-to-install": "mkdir -p $HOME/.sl-luau && cp ./dist/* $HOME/.sl-luau/.", diff --git a/src/lsl/lsl-builtins.ts b/src/lsl/lsl-builtins.ts new file mode 100644 index 0000000..aea1033 --- /dev/null +++ b/src/lsl/lsl-builtins.ts @@ -0,0 +1,173 @@ +import { LSLDef } from "../xml/xml-lsl-json-gen.ts"; +import { ConstDef, EventDef, FuncArg, FuncDef } from "../types.d.ts"; + +type LSLBuiltIns = { + consts: LSLBuiltInConst[]; + functions: LSLBuiltInFunction[]; + events: LSLBuiltInEvent[]; +}; + +type LSLBuiltInType = + | "integer" + | "string" + | "float" + | "rotation" + | "vector" + | "key" + | "list" + | "void"; + +type LSLTypedName = { + name: string; + type: LSLBuiltInType; +}; + +type LSLBuiltInConst = { + value: string; +} & LSLTypedName; + +type LSLBuiltInEvent = { + name: string; + args: LSLTypedName[]; +}; + +type LSLBuiltInFunction = { + args: LSLTypedName[]; +} & LSLTypedName; + +export function buildLSLBuiltInsString(lsl: LSLDef): string { + const date = new Date(); + const output: string[] = [ + `// Generated by https://github.com/WolfGangS/sl_lua_types on ${date.toString()}`, + ]; + + const builtins = buildLSLBuiltIns(lsl); + + for (const func of builtins.functions) { + const args = func.args.map((arg) => `${arg.type} ${arg.name}`).join( + ", ", + ); + output.push(`${func.type} ${func.name}( ${args} )`); + } + + for (const con of builtins.consts) { + output.push(`const ${con.type} ${con.name} = ${con.value}`); + } + + for (const event of builtins.events) { + const args = event.args.map((arg) => `${arg.type} ${arg.name}`).join( + ", ", + ); + output.push(`event ${event.name}( ${args} )`); + } + + return output.join("\n") + "\n"; +} + +export function buildLSLBuiltIns(lsl: LSLDef): LSLBuiltIns { + const builtins: LSLBuiltIns = { + consts: [], + functions: [], + events: [], + }; + + for (const cName in lsl.constants) { + const lCon = lsl.constants[cName]; + const con: LSLBuiltInConst = { + name: cName, + type: castLSLTypeToBuiltIn(lCon.type), + value: castLSLValueToBuiltIn(lCon), + }; + builtins.consts.push(con); + } + + for (const fName in lsl.functions) { + builtins.functions.push(createBuiltInFunc(lsl.functions[fName])); + } + + for (const eName in lsl.events) { + builtins.events.push(createBuiltInEvent(lsl.events[eName])); + } + + return builtins; +} + +function createBuiltInEvent(lEvent: EventDef): LSLBuiltInEvent { + const event: LSLBuiltInEvent = { + name: lEvent.name, + args: castArgs(lEvent.args), + }; + return event; +} + +function castLSLValueToBuiltIn(con: ConstDef): string { + switch (con.type) { + case "string": { + const str = (con.valueRaw || "").replaceAll("\\\\u", "\\u"); + const u_str = JSON.parse(`"${str}"`); + const b_str = u_str.replaceAll("\\\\", "\\"); + const x_str = b_str.replace( + /(?:\\x[\da-fA-F]{2})+/g, + (m) => decodeURIComponent(m.replace(/\\x/g, "%")), + ); + return `"${x_str}"`; + } + case "integer": + case "float": + case "vector": + case "rotation": + return `${con.valueRaw}`; + default: + console.error(con); + throw new Error(`Unhandled Type ${con.type}`); + } +} + +function createBuiltInFunc(lFunc: FuncDef): LSLBuiltInFunction { + try { + const name = lFunc.name; + const args: LSLTypedName[] = castArgs(lFunc.args); + return { + name, + type: castLSLTypeToBuiltIn(lFunc.result), + args, + }; + } catch (e) { + console.error(lFunc); + throw e; + } +} + +function castArgs(lArgs: FuncArg[]): LSLTypedName[] { + const args: LSLTypedName[] = []; + for (const lArg of lArgs) { + args.push({ + name: lArg.name, + type: castLSLTypeToBuiltIn(lArg.type, false), + }); + } + return args; +} + +function castLSLTypeToBuiltIn( + type: string | null, + allowVoid: boolean = true, +): LSLBuiltInType { + switch (type) { + case "string": + case "integer": + case "list": + case "key": + case "vector": + case "rotation": + case "float": + return type; + case "void": + if (!allowVoid) { + throw "Dissalowed void"; + } + return type; + default: + throw new Error(`Unhandled type '${type}'`); + } +} diff --git a/src/main.ts b/src/main.ts index 317cfd7..3684dfc 100644 --- a/src/main.ts +++ b/src/main.ts @@ -7,6 +7,10 @@ import { buildSluaSelene } from "./slua/slua-sele-gen.ts"; import { buildSluaSeleneConfig } from "./slua/slua-sele-conf-gen.ts"; import { buildSluaVSCodeSnippets } from "./slua/slua-vsc-snippets-gen.ts"; import { buildLSLJsonFromYML } from "./yaml/readLSLDefinitionsYAML.ts"; +import { + buildLSLBuiltIns, + buildLSLBuiltInsString, +} from "./lsl/lsl-builtins.ts"; const keywordsFile = Deno.args[0]; const output = Deno.args[1]; @@ -34,6 +38,11 @@ switch (output) { JSON.stringify(lslDef, null, 2), ); break; + case "lsl-builtins": + console.log( + buildLSLBuiltInsString(lslDef), + ); + break; case "slua-json": console.log( JSON.stringify(