diff --git a/spin2/CHANGELOG.md b/spin2/CHANGELOG.md index deeac0d..4db1549 100644 --- a/spin2/CHANGELOG.md +++ b/spin2/CHANGELOG.md @@ -22,8 +22,13 @@ Possible next additions: Update P1 and P2 -- Awaken First draft of Code Folding - - folds code blocks, continued lines, pasm code, and comment blocks +- Awaken First draft of Code Folding: + - folds code blocks, continued lines, pasm code, and comment blocks + - UP NEXT: fold spin language itself (repeat, if, case, etc.) + +Update P1 + +- Repair more Pasm syntax highlighing ## [2.2.7] 2023-11-24 diff --git a/spin2/README.md b/spin2/README.md index e689485..f0a14fc 100644 --- a/spin2/README.md +++ b/spin2/README.md @@ -90,8 +90,9 @@ Peek at or go to the definition of variables/methods from where the variables/me Provides Spin specific code folding support -- Fold Block comments, code blocks (CON, VAR, PUB, etc.), indented flow control, and continued line groups +- Fold Block comments, code blocks (CON, VAR, PUB, etc.), and continued lines - This is controlled by editor settings: Editor: **Folding**, Editor: **Folding Strategy** and Editor: **Show Folding Controls** +- Up Next: fold indented flow control within Spin code ## Feature: Generate "Object public interface" documentation @@ -188,7 +189,7 @@ PRI pullUpValueForEnum(ePullupRqst) : pullup We are working on fixes to the following issues we've seen during our testing. However, they are not major enough to prevent this release. -- The spin2 line-continuation syntax is supported only in OBJ block and on PUB/PRI declaration lines for now. More support coming! +- The spin2 line-continuation syntax is supported only in OBJ block and on PUB/PRI declaration lines for now. More support coming! - We are still working through validating the P1 support against the full P1 obex - this is a work in progress - Some line comments are not properly colored - Occasionally [byte|word|long] storage types are not properly colored diff --git a/spin2/package.json b/spin2/package.json index 59966e7..041e437 100644 --- a/spin2/package.json +++ b/spin2/package.json @@ -5,7 +5,7 @@ "icon": "images/Propeller.ico", "author": "IronSheep", "license": "MIT", - "version": "2.2.7", + "version": "2.2.8", "repository": { "type": "git", "url": "https://github.com/ironsheep/P2-vscode-langserv-extension" diff --git a/spin2/scripts/LIVE-package.json b/spin2/scripts/LIVE-package.json index 59966e7..041e437 100644 --- a/spin2/scripts/LIVE-package.json +++ b/spin2/scripts/LIVE-package.json @@ -5,7 +5,7 @@ "icon": "images/Propeller.ico", "author": "IronSheep", "license": "MIT", - "version": "2.2.7", + "version": "2.2.8", "repository": { "type": "git", "url": "https://github.com/ironsheep/P2-vscode-langserv-extension" diff --git a/spin2/scripts/TEST-package.json b/spin2/scripts/TEST-package.json index eef115a..3577fda 100644 --- a/spin2/scripts/TEST-package.json +++ b/spin2/scripts/TEST-package.json @@ -4,7 +4,7 @@ "description": "P1 and P2 Spin/Pasm Syntax/Semantic Highlighting w/Code Outline, Object Outline and Custom tabbing support", "author": "IronSheep", "license": "MIT", - "version": "2.2.7", + "version": "2.2.8", "repository": { "type": "git", "url": "https://github.com/ironsheep/P2-vscode-langserv-extension" diff --git a/spin2/server/src/parser/spin1.documentSemanticParser.ts b/spin2/server/src/parser/spin1.documentSemanticParser.ts index 433fe92..940d522 100644 --- a/spin2/server/src/parser/spin1.documentSemanticParser.ts +++ b/spin2/server/src/parser/spin1.documentSemanticParser.ts @@ -568,8 +568,8 @@ export class Spin1DocumentSemanticParser { const nonCommentOffset = line.indexOf(nonCommentLineRemainder, 0); // lineNumber, currentOffset, line, allowLocalVarStatus, this.showPAsmCode const allowLocalVarStatus: boolean = false; - const NOT_DAT_PASM: boolean = false; - const partialTokenSet: IParsedToken[] = this._reportDAT_ValueDeclarationCode(i, nonCommentOffset + orgOffset + orgStr.length, line, allowLocalVarStatus, this.showDAT, NOT_DAT_PASM); + const IN_DAT_PASM: boolean = true; + const partialTokenSet: IParsedToken[] = this._reportDAT_ValueDeclarationCode(i, nonCommentOffset + orgOffset + orgStr.length, line, allowLocalVarStatus, this.showDAT, IN_DAT_PASM); partialTokenSet.forEach((newToken) => { tokenSet.push(newToken); }); @@ -1401,11 +1401,11 @@ export class Spin1DocumentSemanticParser { let possibleNameSet: string[] = [namePart]; if (namePart.includes(".") && !namePart.startsWith(".")) { refChar = "."; - possibleNameSet = namePart.split("."); + possibleNameSet = namePart.split(".").filter(Boolean); this._logSPIN(" -- . possibleNameSet=[" + possibleNameSet + "]"); } else if (namePart.includes("#")) { refChar = "#"; - possibleNameSet = namePart.split("#"); + possibleNameSet = namePart.split("#").filter(Boolean); this._logSPIN(" -- # possibleNameSet=[" + possibleNameSet + "]"); } namePart = possibleNameSet[0]; @@ -1543,7 +1543,7 @@ export class Spin1DocumentSemanticParser { } else if ( !this.parseUtils.isP1AsmReservedSymbols(newName) && !this.parseUtils.isP1AsmInstruction(newName) && - !this.parseUtils.isP1AsmConditional(newName) && + !this.parseUtils.isP1AsmEffect(newName) && !this.parseUtils.isDatStorageType(newName) && !this.parseUtils.isBuiltinReservedWord(newName) && !this.parseUtils.isSpinReservedWord(newName) && @@ -1563,8 +1563,8 @@ export class Spin1DocumentSemanticParser { // process remainder of line currentOffset = line.indexOf(lineParts[1], nameOffset + newName.length); const allowLocalVarStatus: boolean = false; - const NOT_DAT_PASM: boolean = false; - const partialTokenSet: IParsedToken[] = this._reportDAT_ValueDeclarationCode(lineIdx, startingOffset, line, allowLocalVarStatus, this.showDAT, NOT_DAT_PASM); + const IN_DAT_PASM: boolean = true; + const partialTokenSet: IParsedToken[] = this._reportDAT_ValueDeclarationCode(lineIdx, startingOffset, line, allowLocalVarStatus, this.showDAT, IN_DAT_PASM); partialTokenSet.forEach((newToken) => { tokenSet.push(newToken); }); @@ -1580,13 +1580,13 @@ export class Spin1DocumentSemanticParser { const tokenSet: IParsedToken[] = []; const lineNbr: number = lineIdx + 1; //this._logMessage(' DBG _reportDAT_ValueDeclarationCode(#' + lineNumber + ', ofs=' + startingOffset + ')'); - this._logDAT("- process ValueDeclaration lineLn#" + lineNbr + " line=[" + line + "]: startingOffset=(" + startingOffset + ")"); + this._logDAT(` - process ValueDeclaration Ln#${lineNbr} isDatPAsm=(${isDatPAsm}), line=[${line}]: ofs=(${startingOffset})`); // process data declaration let currentOffset: number = this.parseUtils.skipWhite(line, startingOffset); const dataValueInitStr = this.parseUtils.getNonCommentLineRemainder(currentOffset, line); if (dataValueInitStr.length > 0) { - this._logDAT(" -- reportDataValueInit dataValueInitStr=[" + dataValueInitStr + "]"); + this._logDAT(` -- reportDataValueInit dataValueInitStr=[${dataValueInitStr}]`); let lineParts: string[] = this.parseUtils.getNonWhiteDataInitLineParts(dataValueInitStr); const argumentStartIndex: number = lineParts.length > 0 && this.parseUtils.isDatStorageType(lineParts[0]) ? 1 : 0; @@ -1609,13 +1609,17 @@ export class Spin1DocumentSemanticParser { continue; } // the following allows '.' in names but only when in DAT PASM code, not spin! - if (possibleName.charAt(0).match(/[a-zA-Z_]/) || (isDatPAsm && possibleName.charAt(0).match(/[a-zA-Z_\.]/))) { + if ( + possibleName.charAt(0).match(/[a-zA-Z_]/) || + (isDatPAsm && possibleName.charAt(0).match(/[a-zA-Z_\:]/)) || + (isDatPAsm && possibleName.charAt(0) == "#" && possibleName.charAt(1).match(/[a-zA-Z_\:]/)) + ) { if (showDebug) { - this._logDAT(" -- possibleName=[" + possibleName + "]"); + this._logDAT(` -- possibleName=[${possibleName}]`); } // does name contain a namespace reference? nameOffset = line.indexOf(possibleName, currentOffset); - if (this._isPossibleObjectReference(possibleName)) { + if (possibleName.includes(".") && this._isPossibleObjectReference(possibleName)) { const bHaveObjReference = this._reportObjectReference(possibleName, lineIdx, nameOffset, line, tokenSet); if (bHaveObjReference) { currentOffset = nameOffset + possibleName.length; @@ -1626,11 +1630,11 @@ export class Spin1DocumentSemanticParser { let possibleNameSet: string[] = [possibleName]; if (possibleName.includes(".") && !namePart.startsWith(".")) { refChar = "."; - possibleNameSet = possibleName.split("."); + possibleNameSet = possibleName.split(".").filter(Boolean); this._logDAT(" -- . possibleNameSet=[" + possibleNameSet + "]"); } else if (possibleName.includes("#")) { refChar = "#"; - possibleNameSet = possibleName.split("#"); + possibleNameSet = possibleName.split("#").filter(Boolean); this._logDAT(" -- # possibleNameSet=[" + possibleNameSet + "]"); } namePart = possibleNameSet[0]; @@ -1664,7 +1668,9 @@ export class Spin1DocumentSemanticParser { !this.parseUtils.isDatNFileStorageType(namePart) && !this.parseUtils.isBinaryOperator(namePart) && !this.parseUtils.isUnaryOperator(namePart) && - !this.parseUtils.isBuiltinReservedWord(namePart) + !this.parseUtils.isP1AsmEffect(namePart) && + !this.parseUtils.isBuiltinReservedWord(namePart) && + !this.parseUtils.isP1AsmConditional(namePart) ) { if (showDebug) { this._logDAT(" -- DAT rDvdc MISSING name=[" + namePart + "]"); @@ -1774,7 +1780,7 @@ export class Spin1DocumentSemanticParser { // skip empty operand continue; } - if (index == lineParts.length - 1 && this.parseUtils.isP1AsmConditional(namePart)) { + if (index == lineParts.length - 1 && this.parseUtils.isP1AsmEffect(namePart)) { // conditional flag-set spec. this._logPASM(" -- SKIP namePart=[" + namePart + "]"); continue; @@ -1799,11 +1805,11 @@ export class Spin1DocumentSemanticParser { let possibleNameSet: string[] = [namePart]; if (namePart.includes(".") && !namePart.startsWith(".")) { refChar = "."; - possibleNameSet = namePart.split("."); + possibleNameSet = namePart.split(".").filter(Boolean); this._logSPIN(" -- . possibleNameSet=[" + possibleNameSet + "]"); } else if (namePart.includes("#")) { refChar = "#"; - possibleNameSet = namePart.split("#"); + possibleNameSet = namePart.split("#").filter(Boolean); this._logSPIN(" -- # possibleNameSet=[" + possibleNameSet + "]"); } namePart = possibleNameSet[0]; @@ -1828,7 +1834,7 @@ export class Spin1DocumentSemanticParser { if ( !this.parseUtils.isP1AsmReservedWord(namePart) && !this.parseUtils.isP1AsmInstruction(namePart) && - !this.parseUtils.isP1AsmConditional(namePart) && + !this.parseUtils.isP1AsmEffect(namePart) && !this.parseUtils.isBinaryOperator(namePart) && !this.parseUtils.isBuiltinReservedWord(namePart) ) { @@ -2436,11 +2442,11 @@ export class Spin1DocumentSemanticParser { let possibleNameSet: string[] = [possibleName]; if (possibleName.includes(".") && !possibleName.startsWith(".")) { refChar = "."; - possibleNameSet = possibleName.split("."); + possibleNameSet = possibleName.split(".").filter(Boolean); this._logSPIN(" -- . possibleNameSet=[" + possibleNameSet + "]"); } else if (possibleName.includes("#")) { refChar = "#"; - possibleNameSet = possibleName.split("#"); + possibleNameSet = possibleName.split("#").filter(Boolean); this._logSPIN(" -- # possibleNameSet=[" + possibleNameSet + "]"); } const namePart = possibleNameSet[0]; diff --git a/spin2/server/src/parser/spin1.documentSymbolParser.ts b/spin2/server/src/parser/spin1.documentSymbolParser.ts index adfce2c..32ffde6 100644 --- a/spin2/server/src/parser/spin1.documentSymbolParser.ts +++ b/spin2/server/src/parser/spin1.documentSymbolParser.ts @@ -169,7 +169,7 @@ export class Spin1DocumentSymbolParser { posssibleLabel = lineParts[1]; if ( posssibleLabel.toUpperCase().startsWith("ORG") || - this.parseUtils.isP1AsmConditional(posssibleLabel) || + this.parseUtils.isP1AsmEffect(posssibleLabel) || this.parseUtils.isP1AsmInstruction(posssibleLabel) || this.parseUtils.isP1AsmReservedSymbols(posssibleLabel) ) { diff --git a/spin2/server/src/parser/spin1.utils.ts b/spin2/server/src/parser/spin1.utils.ts index b97321e..15cd5cb 100644 --- a/spin2/server/src/parser/spin1.utils.ts +++ b/spin2/server/src/parser/spin1.utils.ts @@ -1657,6 +1657,46 @@ export class Spin1ParseUtils { } public isP1AsmConditional(name: string): boolean { + // mark these RED if seen in P2 code + const p1AsmConditions: string[] = [ + "if_always", + "if_never", + "if_e", + "if_ne", + "if_a", + "if_b", + "if_ae", + "if_be", + "if_c", + "if_nc", + "if_z", + "if_nz", + "if_c_eq_z", + "if_c_ne_z", + "if_c_and_z", + "if_c_and_nz", + "if_nc_and_z", + "if_nc_and_nz", + "if_c_or_z", + "if_c_or_nz", + "if_nc_or_z", + "if_nc_or_nz", + "if_z_eq_c", + "if_z_ne_c", + "if_z_and_c", + "if_z_and_nc", + "if_nz_and_c", + "if_nz_and_nc", + "if_z_or_c", + "if_z_or_nc", + "if_nz_or_c", + "if_nz_or_nc", + ]; + const conditionStatus: boolean = p1AsmConditions.indexOf(name.toLowerCase()) != -1; + return conditionStatus; + } + + public isP1AsmEffect(name: string): boolean { let returnStatus: boolean = false; if (name.length >= 2) { const checkType: string = name.toUpperCase(); @@ -1680,7 +1720,7 @@ export class Spin1ParseUtils { haveLabelStatus = false; } else if (name.toUpperCase().startsWith("IF_")) { haveLabelStatus = false; - } else if (this.isP1AsmConditional(name)) { + } else if (this.isP1AsmEffect(name)) { haveLabelStatus = false; } else if (this.isP1AsmInstruction(name)) { haveLabelStatus = false; @@ -1793,7 +1833,7 @@ export class Spin1ParseUtils { return false; } - public isP2AsmConditional(name: string): boolean { + public isP2AsmEffect(name: string): boolean { return false; } diff --git a/spin2/server/src/parser/spin2.documentSemanticParser.ts b/spin2/server/src/parser/spin2.documentSemanticParser.ts index 08b5f42..4a088f8 100644 --- a/spin2/server/src/parser/spin2.documentSemanticParser.ts +++ b/spin2/server/src/parser/spin2.documentSemanticParser.ts @@ -1431,7 +1431,7 @@ export class Spin2DocumentSemanticParser { // add p1asm detect !this.parseUtils.isP1AsmInstruction(newName) && !this.parseUtils.isP1AsmVariable(newName) && - !this.parseUtils.isP1AsmConditional(newName) + !this.parseUtils.isBadP1AsmEffectOrConditional(newName) ) { const nameType: string = isNamedDataDeclarationLine ? "variable" : "label"; var labelModifiers: string[] = ["declaration"]; @@ -2512,7 +2512,7 @@ export class Spin2DocumentSemanticParser { ptTokenType: referenceDetails.type, ptTokenModifiers: modifiersWDecl, }); - } else if (this.parseUtils.isP1AsmInstruction(newName) || this.parseUtils.isP1AsmConditional(newName) || this.parseUtils.isP1AsmVariable(newName)) { + } else if (this.parseUtils.isP1AsmInstruction(newName) || this.parseUtils.isBadP1AsmEffectOrConditional(newName) || this.parseUtils.isP1AsmVariable(newName)) { this._logMessage(" -- ERROR p1asm name=[" + newName + "]"); this._recordToken(tokenSet, line, { line: lineIdx, @@ -2785,7 +2785,7 @@ export class Spin2DocumentSemanticParser { // skip empty operand or ":" left by splitter continue; } - if (index == lineParts.length - 1 && this.parseUtils.isP2AsmConditional(argumentName)) { + if (index == lineParts.length - 1 && this.parseUtils.isP2AsmEffect(argumentName)) { // conditional flag-set spec. this._logPASM(" -- SKIP argumentName=[" + argumentName + "]"); continue; @@ -2834,7 +2834,7 @@ export class Spin2DocumentSemanticParser { if ( !this.parseUtils.isP2AsmReservedWord(namePart) && !this.parseUtils.isP2AsmInstruction(namePart) && - !this.parseUtils.isP2AsmConditional(namePart) && + !this.parseUtils.isP2AsmEffect(namePart) && !this.parseUtils.isBinaryOperator(namePart) && !this.parseUtils.isBuiltinStreamerReservedWord(namePart) && !this.parseUtils.isCoginitReservedSymbol(namePart) && @@ -4906,7 +4906,7 @@ export class Spin2DocumentSemanticParser { // skip empty operand continue; } - if (index == lineParts.length - 1 && this.parseUtils.isP2AsmConditional(argumentName)) { + if (index == lineParts.length - 1 && this.parseUtils.isP2AsmEffect(argumentName)) { // conditional flag-set spec. this._logPASM(" -- SKIP argumentName=[" + argumentName + "]"); continue; diff --git a/spin2/server/src/parser/spin2.documentSymbolParser.ts b/spin2/server/src/parser/spin2.documentSymbolParser.ts index 8cc397f..c71e77d 100644 --- a/spin2/server/src/parser/spin2.documentSymbolParser.ts +++ b/spin2/server/src/parser/spin2.documentSymbolParser.ts @@ -191,7 +191,7 @@ export class Spin2DocumentSymbolParser { posssibleLabel = lineParts[1]; if ( posssibleLabel.toUpperCase().startsWith("ORG") || - this.parseUtils.isP2AsmConditional(posssibleLabel) || + this.parseUtils.isP2AsmEffect(posssibleLabel) || this.parseUtils.isP2AsmInstruction(posssibleLabel) || this.parseUtils.isP2AsmReservedWord(posssibleLabel) ) { @@ -379,7 +379,7 @@ export class Spin2DocumentSymbolParser { // add p1asm detect !this.parseUtils.isP1AsmInstruction(newName) && !this.parseUtils.isP1AsmVariable(newName) && - !this.parseUtils.isP1AsmConditional(newName) + !this.parseUtils.isBadP1AsmEffectOrConditional(newName) ) { if (!isDataDeclarationLine && !newName.startsWith(".") && !newName.startsWith(":") && !newName.includes("#")) { newGlobalLabel = newName; diff --git a/spin2/server/src/parser/spin2.utils.ts b/spin2/server/src/parser/spin2.utils.ts index 92bc56b..c79ddf7 100644 --- a/spin2/server/src/parser/spin2.utils.ts +++ b/spin2/server/src/parser/spin2.utils.ts @@ -2752,8 +2752,8 @@ export class Spin2ParseUtils { return illegalStatus; } - public isP1AsmConditional(name: string): boolean { - let returnStatus: boolean = this.isP1AsmEffect(name); + public isBadP1AsmEffectOrConditional(name: string): boolean { + let returnStatus: boolean = this.isBadP1AsmEffect(name); if (name.length >= 2) { const checkType: string = name.toUpperCase(); if (checkType == "IF_ALWAYS" || checkType == "IF_NEVER") { @@ -2763,7 +2763,7 @@ export class Spin2ParseUtils { return returnStatus; } - public isP1AsmEffect(name: string): boolean { + public isBadP1AsmEffect(name: string): boolean { let returnStatus: boolean = false; if (name.length >= 2) { const checkType: string = name.toUpperCase(); @@ -2774,7 +2774,7 @@ export class Spin2ParseUtils { return returnStatus; } - public isP2AsmConditional(name: string): boolean { + public isP2AsmEffect(name: string): boolean { let returnStatus: boolean = false; if (name.length >= 2) { const checkType: string = name.toUpperCase(); @@ -2809,13 +2809,13 @@ export class Spin2ParseUtils { haveLabelStatus = false; } else if (name.toUpperCase().startsWith("IF_") || name.toUpperCase() == "_RET_") { haveLabelStatus = false; - } else if (this.isP2AsmConditional(name)) { + } else if (this.isP2AsmEffect(name)) { haveLabelStatus = false; } else if (this.isP2AsmNonArgumentInstruction(name)) { haveLabelStatus = false; } else if (this.isP2AsmInstruction(name)) { haveLabelStatus = false; - } else if (this.isP1AsmConditional(name) && !this.isP1AsmEffect(name)) { + } else if (this.isBadP1AsmEffectOrConditional(name) && !this.isBadP1AsmEffect(name)) { haveLabelStatus = false; } else if (this.isP1AsmInstruction(name)) { haveLabelStatus = false;