mirror of
https://github.com/Ed94/pikuma_ps1.git
synced 2026-08-16 22:21:33 +00:00
more theme stuff
This commit is contained in:
+5
-1
@@ -64,7 +64,9 @@ function instructionType(name, index) {
|
||||
if (domain === "component") return "tapeComponentInstruction";
|
||||
if (/^gte_(?!cr_)/.test(name)) return "tapeGteInstruction";
|
||||
if (/^gp[01]_/.test(name)) return "tapeGpuInstruction";
|
||||
if (/^mac_/.test(name)) return "tapeComponentInstruction";
|
||||
if (/^mac_gte_/.test(name)) return "tapeGteInstruction";
|
||||
if (/^mac_gp/.test(name)) return "tapeGpuInstruction";
|
||||
if (/^mac_/.test(name)) return "tapeCpuInstruction";
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -82,6 +84,8 @@ function isRegUseAccess(tokens, tokenIndex) {
|
||||
if (!prev || prev.text !== ".") return false;
|
||||
const prevPrev = tokens[tokenIndex - 2];
|
||||
if (!prevPrev || prevPrev.kind !== "identifier") return false;
|
||||
const next = tokens[tokenIndex + 1];
|
||||
if (next && next.text === ".") return false;
|
||||
if (prevPrev.text === "r") return true;
|
||||
const prev3 = tokens[tokenIndex - 3];
|
||||
const prev4 = tokens[tokenIndex - 4];
|
||||
|
||||
+18
-18
@@ -21,24 +21,24 @@
|
||||
},
|
||||
"contributes": {
|
||||
"semanticTokenTypes": [
|
||||
{ "id": "tapeAtomKeyword", "description": "Tape atom declaration keyword" },
|
||||
{ "id": "tapeAtomName", "description": "Tape atom name" },
|
||||
{ "id": "tapeComponentKeyword", "description": "Tape atom component declaration keyword" },
|
||||
{ "id": "tapeComponentName", "description": "Tape atom component name" },
|
||||
{ "id": "tapeAnnotation", "description": "Tape atom annotation" },
|
||||
{ "id": "tapeBindType", "description": "Tape bind structure type" },
|
||||
{ "id": "tapePhase", "description": "Tape atom phase" },
|
||||
{ "id": "tapeLabel", "description": "Tape atom branch label" },
|
||||
{ "id": "tapeCpuInstruction", "description": "MIPS CPU instruction emitter" },
|
||||
{ "id": "tapeControlFlow", "description": "MIPS branch or jump instruction" },
|
||||
{ "id": "tapeGteInstruction", "description": "GTE instruction emitter" },
|
||||
{ "id": "tapeGpuInstruction", "description": "GPU command emitter" },
|
||||
{ "id": "tapeComponentInstruction", "description": "Tape atom component invocation" },
|
||||
{ "id": "tapeDelaySlot", "description": "Load or branch delay slot annotation" },
|
||||
{ "id": "tapeGprRegister", "description": "MIPS GPR alias" },
|
||||
{ "id": "tapeCop2Register", "description": "COP2 data or control register alias" },
|
||||
{ "id": "tapeDuffleType", "description": "Duffle type or type constructor" },
|
||||
{ "id": "tapeAttribute", "description": "Duffle linkage or storage attribute" }
|
||||
{ "id": "tapeAtomKeyword", "superType": "keyword", "description": "Tape atom declaration keyword" },
|
||||
{ "id": "tapeAtomName", "superType": "function", "description": "Tape atom name" },
|
||||
{ "id": "tapeComponentKeyword", "superType": "keyword", "description": "Tape atom component declaration keyword" },
|
||||
{ "id": "tapeComponentName", "superType": "function", "description": "Tape atom component name" },
|
||||
{ "id": "tapeAnnotation", "superType": "macro", "description": "Tape atom annotation" },
|
||||
{ "id": "tapeBindType", "superType": "type", "description": "Tape bind structure type" },
|
||||
{ "id": "tapePhase", "superType": "label", "description": "Tape atom phase" },
|
||||
{ "id": "tapeLabel", "superType": "label", "description": "Tape atom branch label" },
|
||||
{ "id": "tapeCpuInstruction", "superType": "macro", "description": "MIPS CPU instruction emitter" },
|
||||
{ "id": "tapeControlFlow", "superType": "keyword", "description": "MIPS branch or jump instruction" },
|
||||
{ "id": "tapeGteInstruction", "superType": "macro", "description": "GTE instruction emitter" },
|
||||
{ "id": "tapeGpuInstruction", "superType": "macro", "description": "GPU command emitter" },
|
||||
{ "id": "tapeComponentInstruction", "superType": "macro", "description": "Tape atom component invocation" },
|
||||
{ "id": "tapeDelaySlot", "superType": "keyword", "description": "Load or branch delay slot annotation" },
|
||||
{ "id": "tapeGprRegister", "superType": "variable", "description": "MIPS GPR alias" },
|
||||
{ "id": "tapeCop2Register", "superType": "variable", "description": "COP2 data or control register alias" },
|
||||
{ "id": "tapeDuffleType", "superType": "type", "description": "Duffle type or type constructor" },
|
||||
{ "id": "tapeAttribute", "superType": "keyword", "description": "Duffle linkage or storage attribute" }
|
||||
],
|
||||
"semanticTokenModifiers": [
|
||||
{ "id": "tapeRead", "description": "Register declared in atom_reads" },
|
||||
|
||||
+14
-2
@@ -100,13 +100,19 @@ function scanSource(source, filePath) {
|
||||
declarations.set(token.start, { role, modifiers });
|
||||
}
|
||||
|
||||
function componentDomain(name) {
|
||||
if (name.startsWith("ac_gte_") || name.startsWith("mac_gte_")) return "gte";
|
||||
if (name.startsWith("ac_gp_") || name.startsWith("mac_gp_")) return "gpu";
|
||||
return "cpu";
|
||||
}
|
||||
|
||||
function addComponent(token) {
|
||||
index.components.add(token.text);
|
||||
mark(token, "componentName");
|
||||
const alias = componentAlias(token.text);
|
||||
if (alias) {
|
||||
index.componentAliases.add(alias);
|
||||
index.macros.set(alias, domain);
|
||||
index.macros.set(alias, componentDomain(token.text));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,7 +167,13 @@ function scanSource(source, filePath) {
|
||||
|
||||
if (token.text === "define" && tokens[tokenIndex - 1] && tokens[tokenIndex - 1].text === "#") {
|
||||
const name = tokens[tokenIndex + 1];
|
||||
if (name && name.kind === "identifier" && name.line === token.line) index.macros.set(name.text, domain);
|
||||
if (name && name.kind === "identifier" && name.line === token.line) {
|
||||
if (/^(?:RegUse_|Struct_|Enum_|Union_|TypeR_|TypeV_|Relative_|Binds_)/.test(name.text)) {
|
||||
index.types.add(name.text);
|
||||
} else {
|
||||
index.macros.set(name.text, domain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (token.text === "typedef") {
|
||||
|
||||
+10
-24
@@ -6,8 +6,7 @@
|
||||
{ "include": "#component-declarations" },
|
||||
{ "include": "#annotation-arguments" },
|
||||
{ "include": "#annotations" },
|
||||
{ "include": "#instructions" },
|
||||
{ "include": "#registers" },
|
||||
{ "include": "#delay-slots" },
|
||||
{ "include": "#types" },
|
||||
{ "include": "#attributes" }
|
||||
],
|
||||
@@ -34,15 +33,11 @@
|
||||
"2": { "name": "entity.name.function.duffle.component" }
|
||||
}
|
||||
},
|
||||
{ "match": "\\bMipsAtomComp_Proc_\\b", "name": "keyword.control.duffle.component" },
|
||||
{ "match": "\\bac_[A-Za-z0-9_]+\\b", "name": "entity.name.function.duffle.component" }
|
||||
{ "match": "\\bMipsAtomComp_Proc_\\b", "name": "keyword.control.duffle.component" }
|
||||
]
|
||||
},
|
||||
"annotation-arguments": {
|
||||
"patterns": [
|
||||
{ "match": "(?<=\\batom_bind\\()\\s*Binds_[A-Za-z0-9_]+", "name": "entity.name.type.duffle.bind" },
|
||||
{ "match": "(?<=\\batom_phase\\()\\s*[A-Za-z_][A-Za-z0-9_]*", "name": "entity.name.tag.duffle.phase" },
|
||||
{ "match": "(?<=\\batom_label\\()\\s*[A-Za-z_][A-Za-z0-9_]*", "name": "entity.name.label.duffle.atom" },
|
||||
{
|
||||
"match": "\\b(atom_offset)\\s*\\(\\s*([A-Za-z_][A-Za-z0-9_]*)\\s*,\\s*([A-Za-z_][A-Za-z0-9_]*)",
|
||||
"captures": {
|
||||
@@ -50,31 +45,22 @@
|
||||
"2": { "name": "entity.name.label.duffle.atom" },
|
||||
"3": { "name": "entity.name.label.duffle.atom" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "match": "(?<=\\batom_bind\\()\\s*Binds_[A-Za-z0-9_]+", "name": "entity.name.type.duffle.bind" },
|
||||
{ "match": "(?<=\\batom_phase\\()\\s*[A-Za-z_][A-Za-z0-9_]*", "name": "entity.name.tag.duffle.phase" },
|
||||
{ "match": "(?<=\\batom_label\\()\\s*[A-Za-z_][A-Za-z0-9_]*", "name": "entity.name.label.duffle.atom" }
|
||||
]
|
||||
},
|
||||
"annotations": {
|
||||
"match": "\\b(atom_info|atom_bind|atom_reads|atom_writes|atom_label|atom_offset|atom_reg|atom_type|atom_ctx|atom_phase|atom_auto_reg|phase_auto_reg|atom_dbg_skip)\\b",
|
||||
"name": "support.function.duffle.annotation"
|
||||
},
|
||||
"instructions": {
|
||||
"patterns": [
|
||||
{ "match": "\\b(branch_|jump_|jump_rel|call_)[A-Za-z0-9_]*\\b", "name": "keyword.control.duffle.branch" },
|
||||
{ "match": "\\b(LdSlot_|BdSlot_)\\b", "name": "keyword.operator.duffle.delayslot" },
|
||||
{ "match": "\\b(load_|store_|add_|sub_|shift_|set_lt_|and_i|or_i|xor_i|nop[0-9]*)[A-Za-z0-9_]*\\b", "name": "support.function.duffle.cpu" },
|
||||
{ "match": "\\bgte_(?!cr_)[A-Za-z0-9_]+\\b", "name": "support.function.duffle.gte" },
|
||||
{ "match": "\\bgp[01]_[A-Za-z0-9_]+\\b", "name": "support.function.duffle.gpu" },
|
||||
{ "match": "\\bmac_[A-Za-z0-9_]+\\b", "name": "support.function.duffle.component" }
|
||||
]
|
||||
},
|
||||
"registers": {
|
||||
"patterns": [
|
||||
{ "match": "\\bR_[A-Za-z0-9_]+\\b", "name": "variable.other.constant.duffle.gpr" },
|
||||
{ "match": "\\b(?:C2_|gte_cr_)[A-Za-z0-9_]+\\b", "name": "variable.other.constant.duffle.cop2" }
|
||||
]
|
||||
"delay-slots": {
|
||||
"match": "\\b(LdSlot_|BdSlot_)\\b",
|
||||
"name": "keyword.operator.duffle.delayslot"
|
||||
},
|
||||
"types": {
|
||||
"match": "\\b(?:[USFB][1248]|MipsAtom|MipsCode|Reg|Binds_[A-Za-z0-9_]+|Struct_|Enum_|Union_|TypeR_|TypeV_)\\b",
|
||||
"match": "\\b(?:Binds_[A-Za-z0-9_]+|RegUse_[A-Za-z0-9_]+)\\b",
|
||||
"name": "storage.type.duffle.type"
|
||||
},
|
||||
"attributes": {
|
||||
|
||||
Binary file not shown.
+1
-1
@@ -67,7 +67,7 @@ test("document-local declarations override an empty workspace index", () => {
|
||||
const result = classifyDocument(source, "C:/x/code/duffle/math.atom.c", createIndex());
|
||||
|
||||
assert.equal(byText(result, "ac_new_component")[0].type, "tapeComponentName");
|
||||
assert.equal(byText(result, "mac_new_component")[0].type, "tapeComponentInstruction");
|
||||
assert.equal(byText(result, "mac_new_component")[0].type, "tapeCpuInstruction");
|
||||
});
|
||||
|
||||
test("classifier returns ordered non-overlapping spans and partial malformed output", () => {
|
||||
|
||||
+15
-17
@@ -10,7 +10,9 @@ const { TOKEN_MODIFIERS, TOKEN_TYPES } = require("../classifier");
|
||||
const ROOT = path.resolve(__dirname, "..");
|
||||
|
||||
function readJson(filePath) {
|
||||
return JSON.parse(fs.readFileSync(filePath, "utf8"));
|
||||
const raw = fs.readFileSync(filePath, "utf8");
|
||||
const stripped = raw.replace(/\/\/.*$/gm, "").replace(/,\s*([}\]])/g, "$1");
|
||||
return JSON.parse(stripped);
|
||||
}
|
||||
|
||||
function collectScopeNames(value, output = new Set()) {
|
||||
@@ -48,15 +50,23 @@ test("package includes runtime files only and acknowledges local-only metadata",
|
||||
assert.equal(packageJson.scripts.package.includes("--skip-license"), true);
|
||||
});
|
||||
|
||||
test("every semantic token has a TextMate fallback scope and grammar scope", () => {
|
||||
test("every semantic token has a scope mapping; DSL-specific tokens also have grammar scopes", () => {
|
||||
const packageJson = readJson(path.join(ROOT, "package.json"));
|
||||
const grammar = readJson(path.join(ROOT, "syntaxes", "tape_atom.tmLanguage.json"));
|
||||
const mappings = packageJson.contributes.semanticTokenScopes[0].scopes;
|
||||
const grammarScopes = collectScopeNames(grammar);
|
||||
|
||||
const grammarRequired = new Set([
|
||||
"tapeAtomKeyword", "tapeAtomName", "tapeComponentKeyword", "tapeComponentName",
|
||||
"tapeAnnotation", "tapeBindType", "tapePhase", "tapeLabel",
|
||||
"tapeDelaySlot", "tapeDuffleType", "tapeAttribute",
|
||||
]);
|
||||
|
||||
for (const tokenType of TOKEN_TYPES) {
|
||||
assert.equal(Array.isArray(mappings[tokenType]), true, `missing scope mapping: ${tokenType}`);
|
||||
assert.equal(mappings[tokenType].some((scope) => grammarScopes.has(scope)), true, `grammar does not emit: ${tokenType}`);
|
||||
if (grammarRequired.has(tokenType)) {
|
||||
assert.equal(mappings[tokenType].some((scope) => grammarScopes.has(scope)), true, `grammar does not emit: ${tokenType}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -72,22 +82,10 @@ test("TextMate offset labels stay scoped to atom_offset calls", () => {
|
||||
assert.equal(offsetRule.captures[3].name, "entity.name.label.duffle.atom");
|
||||
});
|
||||
|
||||
test("workspace enables semantic highlighting and colors every custom token", () => {
|
||||
test("workspace enables semantic highlighting", () => {
|
||||
const settings = readJson(path.resolve(ROOT, "..", "settings.json"));
|
||||
const semantic = settings["editor.semanticTokenColorCustomizations"];
|
||||
|
||||
assert.equal(settings["editor.semanticHighlighting.enabled"], true);
|
||||
const semantic = settings["editor.semanticTokenColorCustomizations"];
|
||||
assert.equal(semantic.enabled, true);
|
||||
for (const tokenType of TOKEN_TYPES) {
|
||||
assert.equal(Object.hasOwn(semantic.rules, tokenType), true, `missing color: ${tokenType}`);
|
||||
}
|
||||
for (const rule of [
|
||||
"tapeGprRegister.tapeRead",
|
||||
"tapeGprRegister.tapeWrite",
|
||||
"tapeCop2Register.tapeRead",
|
||||
"tapeCop2Register.tapeWrite",
|
||||
"*.tapeAuto",
|
||||
]) {
|
||||
assert.equal(Object.hasOwn(semantic.rules, rule), true, `missing modifier color: ${rule}`);
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user