Skip to content

Commit

Permalink
Merge pull request #33 from deleterium/feat/warningNotInitialized
Browse files Browse the repository at this point in the history
New feature: Warning not initialized variables
  • Loading branch information
deleterium authored Feb 10, 2024
2 parents a03032b + ae29dfa commit 4784a93
Show file tree
Hide file tree
Showing 7 changed files with 61 additions and 12 deletions.
20 changes: 10 additions & 10 deletions src/__tests__/misc.a.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,44 +213,44 @@ 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()
expect(compiler.getAssemblyCode()).toBe(assembly)
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()
expect(compiler.getAssemblyCode()).toBe(assembly)
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()
expect(compiler.getAssemblyCode()).toBe(assembly)
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()
expect(compiler.getAssemblyCode()).toBe(assembly)
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()
Expand Down
16 changes: 15 additions & 1 deletion src/__tests__/warnings.a.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
4 changes: 3 additions & 1 deletion src/codeGenerator/astProcessor/binaryAsnProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 18 additions & 0 deletions src/codeGenerator/astProcessor/setupGenCode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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++
Expand Down
4 changes: 4 additions & 0 deletions src/shaper/memoryProcessor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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 = {
Expand Down
9 changes: 9 additions & 0 deletions src/shaper/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function getTypeDefinitionTemplate<T extends 'register'|'long'|'fixed'|'s
RetObj.MemoryTemplate.declaration = 'long'
RetObj.MemoryTemplate.size = 1
RetObj.MemoryTemplate.isDeclared = true
RetObj.MemoryTemplate.isSet = true
break
case 'long':
case 'void':
Expand Down Expand Up @@ -67,6 +68,7 @@ const longArg : MEMORY_SLOT = {
type: 'long',
scope: 'dummy',
declaration: 'long',
isSet: false,
size: 1,
isDeclared: true
}
Expand All @@ -78,6 +80,7 @@ const longPtrArg : MEMORY_SLOT = {
type: 'long',
scope: 'dummy',
declaration: 'long_ptr',
isSet: false,
size: 1,
isDeclared: true
}
Expand All @@ -89,6 +92,7 @@ const fixedArg : MEMORY_SLOT = {
type: 'fixed',
scope: 'dummy',
declaration: 'fixed',
isSet: false,
size: 1,
isDeclared: true
}
Expand All @@ -98,6 +102,7 @@ export const autoCounterTemplate : MEMORY_SLOT = {
asmName: '_counterTimestamp',
declaration: 'long',
isDeclared: true,
isSet: false,
name: '_counterTimestamp',
scope: '',
size: 1,
Expand Down Expand Up @@ -139,6 +144,7 @@ export const BuiltInTemplate: SC_FUNCTION[] = [
type: 'long',
scope: 'memcopy',
declaration: 'void_ptr',
isSet: false,
size: 1,
isDeclared: true
},
Expand All @@ -149,6 +155,7 @@ export const BuiltInTemplate: SC_FUNCTION[] = [
type: 'long',
scope: 'memcopy',
declaration: 'void_ptr',
isSet: false,
size: 1,
isDeclared: true
}
Expand Down Expand Up @@ -561,6 +568,7 @@ export function getMemoryTemplate (memType: MEMORY_BASE_TYPES) : MEMORY_SLOT {
asmName: '',
isDeclared: false,
declaration: '',
isSet: false,
address: -1,
name: '',
scope: '',
Expand All @@ -573,6 +581,7 @@ export const fixedBaseTemplate : MEMORY_SLOT = {
asmName: 'f100000000',
declaration: 'fixed',
isDeclared: false,
isSet: true,
name: 'f100000000',
hexContent: '0000000005f5e100',
scope: '',
Expand Down
2 changes: 2 additions & 0 deletions src/typings/syntaxTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export type MEMORY_SLOT = {
isDeclared: boolean
/** Variable type during declaration */
declaration: DECLARATION_TYPES
/** Control warning if using variables before setting it. */
isSet: boolean
/** Offset in memory. -1 if this slot is not in memory */
address: number
/** Variable name */
Expand Down

0 comments on commit 4784a93

Please sign in to comment.