diff --git a/src/__tests__/misc.a.spec.ts b/src/__tests__/misc.a.spec.ts index f1fe2bf..f455bc1 100644 --- a/src/__tests__/misc.a.spec.ts +++ b/src/__tests__/misc.a.spec.ts @@ -213,8 +213,8 @@ describe('Wrong code to check error safeguards', () => { describe('Warnings', () => { it('should compile with warning: right side of operator', () => { - const code = 'long la, lb; fixed fa, fb; fa = fb - la;' - const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @fa $fb\nSET @r0 $la\nMUL @r0 $f100000000\nSUB @fa $r0\nFIN\n' + const code = 'long la=0, lb; fixed fa, fb=0.0; fa = fb - la;' + const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nCLR @la\nCLR @fb\nSET @fa $fb\nSET @r0 $la\nMUL @r0 $f100000000\nSUB @fa $r0\nFIN\n' const warnings = "Warning: at line 1. Implicit type casting conversion on right side of operator '-'." const compiler = new SmartC({ language: 'C', sourceCode: code }) compiler.compile() @@ -222,8 +222,8 @@ describe('Warnings', () => { expect(compiler.getMachineCode().Warnings).toBe(warnings) }) it('should compile with warning: left side of operator', () => { - const code = 'long la, lb; fixed fa, fb; fa = la - fb;' - const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @fa $la\nMUL @fa $f100000000\nSUB @fa $fb\nFIN\n' + const code = 'long la=2, lb; fixed fa, fb=0.0; fa = la - fb;\n#pragma optimizationLevel 0' + const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @la #0000000000000002\nCLR @fb\nSET @fa $la\nMUL @fa $f100000000\nSUB @fa $fb\nFIN\n' const warnings = "Warning: at line 1. Implicit type casting conversion on left side of operator '-'." const compiler = new SmartC({ language: 'C', sourceCode: code }) compiler.compile() @@ -231,8 +231,8 @@ describe('Warnings', () => { expect(compiler.getMachineCode().Warnings).toBe(warnings) }) it('should compile with warning: rigth side of comparision', () => { - const code = 'long la, lb; fixed fa, fb; if(fa < lb) la++;' - const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @r0 $lb\nMUL @r0 $f100000000\nBLT $fa $r0 :__opt_1\nFIN\n__opt_1:\nINC @la\nFIN\n' + const code = 'long la, lb=10; fixed fa=1.0; if(fa < lb) la=1;\n#pragma optimizationLevel 0' + const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n\nSET @lb #000000000000000a\nSET @fa $f100000000\nSET @r0 $lb\nMUL @r0 $f100000000\nBGE $fa $r0 :__if1_endif\n__if1_start:\nSET @la #0000000000000001\n__if1_endif:\nFIN\n' const warnings = "Warning: at line 1. Implicit type casting conversion on right side of comparision '<'." const compiler = new SmartC({ language: 'C', sourceCode: code }) compiler.compile() @@ -240,8 +240,8 @@ describe('Warnings', () => { expect(compiler.getMachineCode().Warnings).toBe(warnings) }) it('should compile with warning: left side of comparision', () => { - const code = 'long la, lb; fixed fa, fb; if(la < fb) la++;' - const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @r0 $la\nMUL @r0 $f100000000\nBLT $r0 $fb :__opt_1\nFIN\n__opt_1:\nINC @la\nFIN\n' + const code = 'long la=1, lb; fixed fa, fb=1.1; if(la < fb) la++;\n#pragma optimizationLevel 0\n' + const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @la #0000000000000001\nSET @fb #00000000068e7780\nSET @r0 $la\nMUL @r0 $f100000000\nBGE $r0 $fb :__if1_endif\n__if1_start:\nINC @la\n__if1_endif:\nFIN\n' const warnings = "Warning: at line 1. Implicit type casting conversion on left side of comparision '<'." const compiler = new SmartC({ language: 'C', sourceCode: code }) compiler.compile() @@ -249,8 +249,8 @@ describe('Warnings', () => { expect(compiler.getMachineCode().Warnings).toBe(warnings) }) it('should compile with warning: right side of assignment', () => { - const code = 'long la, lb; fixed fa, fb; la = fb;' - const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nSET @la $fb\nDIV @la $f100000000\nFIN\n' + const code = 'long la, lb; fixed fa, fb=0.0; la = fb;' + const assembly = '^declare r0\n^declare r1\n^declare r2\n^declare f100000000\n^const SET @f100000000 #0000000005f5e100\n^declare la\n^declare lb\n^declare fa\n^declare fb\n\nCLR @fb\nSET @la $fb\nDIV @la $f100000000\nFIN\n' const warnings = "Warning: at line 1. Implicit type casting conversion on right side of assignment '='." const compiler = new SmartC({ language: 'C', sourceCode: code }) compiler.compile() diff --git a/src/__tests__/warnings.a.spec.ts b/src/__tests__/warnings.a.spec.ts index 629394d..bcc8f8b 100644 --- a/src/__tests__/warnings.a.spec.ts +++ b/src/__tests__/warnings.a.spec.ts @@ -2,7 +2,21 @@ import { SmartC } from '../smartc' describe('Warnings', () => { it('should not warn: add or sub pointers with longs values (struct_ptr)', () => { - const code = 'search(2);\nstruct PLAYER { long address, balance, VDLS; } *playerPtr, players[2];\nstruct PLAYER * search(long playerAddress) {\nlong nPlayers;\n struct PLAYER * foundPlayer;\n foundPlayer = &players[0];\n for (long auxI = 0; auxI < nPlayers; auxI++) {\n if (foundPlayer->address == playerAddress) {\n return foundPlayer;\n }\n foundPlayer += (sizeof(struct PLAYER));\n foundPlayer = foundPlayer + (sizeof(struct PLAYER));\n foundPlayer++;\n }\n return NULL;\n}' + const code = 'search(2);\nstruct PLAYER { long address, balance, VDLS; } *playerPtr, players[2];\nstruct PLAYER * search(long playerAddress) {\nlong nPlayers=0;\n struct PLAYER * foundPlayer;\n foundPlayer = &players[0];\n for (long auxI = 0; auxI < nPlayers; auxI++) {\n if (foundPlayer->address == playerAddress) {\n return foundPlayer;\n }\n foundPlayer += (sizeof(struct PLAYER));\n foundPlayer = foundPlayer + (sizeof(struct PLAYER));\n foundPlayer++;\n }\n return NULL;\n}' + const warnings = '' + const compiler = new SmartC({ language: 'C', sourceCode: code }) + compiler.compile() + expect(compiler.getMachineCode().Warnings).toBe(warnings) + }) + it('should warn: longs used before initialization', () => { + const code = 'struct PLAYER { long sa, sb; } player;\nlong a, b;\nlong message[4];\n\na+=1;\na = message[b];\na = player.sb;\n' + const warnings = "Warning: at line 5. Variable 'a' is used but not initialized.\nWarning: at line 6. Variable 'b' is used but not initialized.\nWarning: at line 7. Variable 'player_sb' is used but not initialized." + const compiler = new SmartC({ language: 'C', sourceCode: code }) + compiler.compile() + expect(compiler.getMachineCode().Warnings).toBe(warnings) + }) + it('should not warn: same as before but initialized', () => { + const code = 'struct PLAYER { long sa, sb; } player;\nlong a, b;\nlong message[4];\n\na=b=1;\na = message[b];\nplayer.sb=message[2];\na = player.sb;\n' const warnings = '' const compiler = new SmartC({ language: 'C', sourceCode: code }) compiler.compile() diff --git a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts index 566a2d3..0d0d276 100644 --- a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts @@ -144,7 +144,9 @@ export default function binaryAsnProcessor ( function assignmentProc () : GENCODE_SOLVED_OBJECT { assignmentStartErrorTests() - AuxVars.isLeftSideOfAssignment = true + if (CurrentNode.Operation.type === 'Assignment') { + AuxVars.isLeftSideOfAssignment = true + } AuxVars.hasVoidArray = false const LGenObj = genCode(Program, AuxVars, { RemAST: CurrentNode.Left, diff --git a/src/codeGenerator/astProcessor/setupGenCode.ts b/src/codeGenerator/astProcessor/setupGenCode.ts index dcd02c0..5b8b45f 100644 --- a/src/codeGenerator/astProcessor/setupGenCode.ts +++ b/src/codeGenerator/astProcessor/setupGenCode.ts @@ -126,6 +126,9 @@ export default function setupGenCode ( if (MemFound === undefined) { throw new Error(`At line: ${line}. Using variable '${varName}' before declaration.`) } + if (!MemFound.isSet) { + detectAndSetNotInitialized(MemFound, line, varDeclaration !== '') + } if (varDeclaration !== '') { // we are in declarations sentence MemFound.isDeclared = true return deepCopy(MemFound) @@ -144,9 +147,24 @@ export default function setupGenCode ( if (FoundMemory === undefined) { throw new Error(`At line: ${line}. No variable found at address '${addr}'.`) } + if (!FoundMemory.isSet) { + detectAndSetNotInitialized(FoundMemory, line, false) + } return deepCopy(FoundMemory) } + function detectAndSetNotInitialized (Memory: MEMORY_SLOT, line: number, isInitialization: boolean) { + if (AuxVars.isLeftSideOfAssignment || Memory.hexContent) { + Memory.isSet = true + return + } + if (isInitialization) { + return + } + AuxVars.warnings.push(`Warning: at line ${line}. Variable '${Memory.name}' is used but not initialized.`) + Memory.isSet = true // No more warning for same variable + } + function auxvarsGetNewJumpID () : string { // This code shall be equal GlobalCodeVars.getNewJumpID() AuxVars.jumpId++ diff --git a/src/shaper/memoryProcessor.ts b/src/shaper/memoryProcessor.ts index 469fe09..cd4f6f4 100644 --- a/src/shaper/memoryProcessor.ts +++ b/src/shaper/memoryProcessor.ts @@ -106,6 +106,7 @@ export default function memoryProcessor ( } } header.isDeclared = AuxVars.isFunctionArgument + header.isSet = AuxVars.isFunctionArgument // If is not an array, just send the header if (dimensions.length === 0) { return [header] @@ -133,6 +134,7 @@ export default function memoryProcessor ( Mem2.asmName = `${header.asmName}_${i - 1}` Mem2.scope = AuxVars.currentScopeName Mem2.declaration = header.ArrayItem.declaration + Mem2.isSet = true // No way to track array items for using before initialized retArrMem.push(Mem2) } // create array type definition @@ -277,6 +279,7 @@ export default function memoryProcessor ( StructMemHeader.asmName = AuxVars.currentPrefix + phraseCode[startingTokenCounter].value StructMemHeader.scope = AuxVars.currentScopeName StructMemHeader.isDeclared = AuxVars.isFunctionArgument + StructMemHeader.isSet = AuxVars.isFunctionArgument return [StructMemHeader] } // It IS array of structs @@ -293,6 +296,7 @@ export default function memoryProcessor ( StructMemHeader.asmName = AuxVars.currentPrefix + phraseCode[startingTokenCounter].value StructMemHeader.scope = AuxVars.currentScopeName StructMemHeader.isDeclared = AuxVars.isFunctionArgument + StructMemHeader.isSet = AuxVars.isFunctionArgument StructMemHeader.type = 'array' StructMemHeader.typeDefinition = StructMemHeader.asmName StructMemHeader.ArrayItem = { diff --git a/src/shaper/templates.ts b/src/shaper/templates.ts index 76a38cb..1e5a56f 100644 --- a/src/shaper/templates.ts +++ b/src/shaper/templates.ts @@ -23,6 +23,7 @@ export function getTypeDefinitionTemplate