From 6580092de59db2250c0676725adf7009dbcc205a Mon Sep 17 00:00:00 2001 From: deleterium Date: Mon, 19 Feb 2024 20:55:27 -0300 Subject: [PATCH 1/5] Refactor: "auxvars" to better place/name: Program.context --- .../assemblyProcessor/assignmentToAsm.ts | 37 +- .../assemblyProcessor/builtinToAsm.ts | 303 ++++++++-------- .../assemblyProcessor/comparisionToAsm.ts | 18 +- .../assemblyProcessor/createInstruction.ts | 63 ++-- .../assemblyProcessor/keywordToAsm.ts | 21 +- .../assemblyProcessor/operatorToAsm.ts | 40 +- .../assemblyProcessor/typeCastingToAsm.ts | 15 +- .../astProcessor/binaryAsnProcessor.ts | 133 +++---- .../astProcessor/endAsnProcessor.ts | 42 ++- .../astProcessor/exceptionAsnProcessor.ts | 12 +- .../astProcessor/functionSolver.ts | 32 +- src/codeGenerator/astProcessor/genCode.ts | 16 +- .../astProcessor/lookupAsnProcessor.ts | 94 ++--- .../astProcessor/setupGenCode.ts | 190 ---------- .../astProcessor/switchAsnProcessor.ts | 12 +- .../astProcessor/unaryAsnProcessor.ts | 119 +++--- src/codeGenerator/codeGenerator.ts | 343 +++++++++++++----- src/codeGenerator/codeGeneratorTypes.ts | 85 ++--- src/typings/contractTypes.ts | 3 + 19 files changed, 775 insertions(+), 803 deletions(-) delete mode 100644 src/codeGenerator/astProcessor/setupGenCode.ts diff --git a/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts b/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts index 14a2fe9..e78496c 100644 --- a/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts @@ -1,6 +1,7 @@ import { assertExpression, assertNotUndefined } from '../../repository/repository' +import { CONTRACT } from '../../typings/contractTypes' import { MEMORY_SLOT, OFFSET_MODIFIER_CONSTANT } from '../../typings/syntaxTypes' -import { FLATTEN_MEMORY_RETURN_OBJECT, GENCODE_AUXVARS } from '../codeGeneratorTypes' +import { FLATTEN_MEMORY_RETURN_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import { flattenMemory } from './createInstruction' @@ -9,7 +10,7 @@ import { flattenMemory } from './createInstruction' * @returns the assembly code necessary for the assignment to happen */ export default function assignmentToAsm ( - auxVars: GENCODE_AUXVARS, Left: MEMORY_SLOT, Right: MEMORY_SLOT, operationLine: string + Program: CONTRACT, Left: MEMORY_SLOT, Right: MEMORY_SLOT, operationLine: string ) : string { /** Main function */ function assignmentToAsmMain (): string { @@ -49,8 +50,8 @@ export default function assignmentToAsm ( case 'constant': return leftRegularOffsetConstantToAsm(Left.Offset) case 'variable': - RightMem = flattenMemory(auxVars, Right, operationLine) - offsetVarName = auxVars.getMemoryObjectByLocation(Left.Offset.addr).asmName + RightMem = flattenMemory(Program, Right, operationLine) + offsetVarName = Program.Context.getMemoryObjectByLocation(Left.Offset.addr).asmName assemblyCode = `SET @($${Left.asmName} + $${offsetVarName}) $${RightMem.FlatMem.asmName}\n` freeIfItIsNew(RightMem) return RightMem.asmCode + assemblyCode @@ -66,7 +67,7 @@ export default function assignmentToAsm ( return leftRegularOffsetUndefinedAndRightConstantOffsetUndefinedToAsm() case 'constant': Right.hexContent = assertNotUndefined(Right.hexContent) - newVarName = auxVars.getMemoryObjectByLocation(utils.addHexSimple(Right.Offset.value, Right.hexContent), operationLine).asmName + newVarName = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(Right.Offset.value, Right.hexContent), operationLine).asmName return `SET @${Left.asmName} $${newVarName}\n` case 'variable': throw new Error('Not implemented.') @@ -87,7 +88,7 @@ export default function assignmentToAsm ( optVarName = 'f' } optVarName += Number('0x' + Right.hexContent).toString(10) - const findOpt = auxVars.memory.find(MEM => MEM.asmName === optVarName && MEM.hexContent === Right.hexContent) + const findOpt = Program.memory.find(MEM => MEM.asmName === optVarName && MEM.hexContent === Right.hexContent) if (findOpt) { return `SET @${Left.asmName} $${findOpt.asmName}\n` } @@ -104,7 +105,7 @@ export default function assignmentToAsm ( case 'constant': return leftRegularOffsetUndefinedAndRightRegularOffsetConstantToAsm(Right.Offset) case 'variable': - offsetVarName = auxVars.getMemoryObjectByLocation(Right.Offset.addr, operationLine).asmName + offsetVarName = Program.Context.getMemoryObjectByLocation(Right.Offset.addr, operationLine).asmName return `SET @${Left.asmName} $($${Right.asmName} + $${offsetVarName})\n` } } @@ -129,7 +130,7 @@ export default function assignmentToAsm ( if (RightOffset.value === 0) { return `SET @${Left.asmName} $($${Right.asmName})\n` } - const MemOffset = flattenMemory(auxVars, utils.createConstantMemObj(RightOffset.value), operationLine) + const MemOffset = flattenMemory(Program, utils.createConstantMemObj(RightOffset.value), operationLine) const assemblyCode = `SET @${Left.asmName} $($${Right.asmName} + $${MemOffset.FlatMem.asmName})\n` freeIfItIsNew(MemOffset) return MemOffset.asmCode + assemblyCode @@ -143,26 +144,26 @@ export default function assignmentToAsm ( } if (Right.Offset.type === 'constant') { const memLoc = utils.addHexSimple(Right.hexContent, Right.Offset.value) - const RightMem = auxVars.getMemoryObjectByLocation(memLoc, operationLine) + const RightMem = Program.Context.getMemoryObjectByLocation(memLoc, operationLine) return `SET @${Left.asmName} $${RightMem.asmName}\n` } // Right.Offset.type is 'variable' - const offsetVarName = auxVars.getMemoryObjectByLocation(Right.Offset.addr, operationLine).asmName + const offsetVarName = Program.Context.getMemoryObjectByLocation(Right.Offset.addr, operationLine).asmName return `SET @${Left.asmName} $($${Right.asmName} + $${offsetVarName})\n` } /** Left type is 'register', 'long' or 'structRef', with offset constant. Create assembly instruction. */ function leftRegularOffsetConstantToAsm (LeftOffset: OFFSET_MODIFIER_CONSTANT) : string { - const RightMem = flattenMemory(auxVars, Right, operationLine) + const RightMem = flattenMemory(Program, Right, operationLine) let assemblyCode: string if (LeftOffset.value === 0) { assemblyCode = `SET @($${Left.asmName}) $${RightMem.FlatMem.asmName}\n` if (RightMem.isNew) { - auxVars.freeRegister(RightMem.FlatMem.address) + Program.Context.freeRegister(RightMem.FlatMem.address) } return RightMem.asmCode + assemblyCode } - const MemOffset = flattenMemory(auxVars, utils.createConstantMemObj(LeftOffset.value), operationLine) + const MemOffset = flattenMemory(Program, utils.createConstantMemObj(LeftOffset.value), operationLine) assemblyCode = `SET @($${Left.asmName} + $${MemOffset.FlatMem.asmName}) $${RightMem.FlatMem.asmName}\n` freeIfItIsNew(MemOffset) freeIfItIsNew(RightMem) @@ -181,8 +182,8 @@ export default function assignmentToAsm ( // Optimimization steps before lead to impossible reach code throw new Error(`Internal error at line: ${operationLine}.`) case 'variable': - RightMem = flattenMemory(auxVars, Right, operationLine) - leftOffsetVarName = auxVars.getMemoryObjectByLocation(Left.Offset.addr, operationLine).asmName + RightMem = flattenMemory(Program, Right, operationLine) + leftOffsetVarName = Program.Context.getMemoryObjectByLocation(Left.Offset.addr, operationLine).asmName assemblyCode = `SET @($${Left.asmName} + $${leftOffsetVarName}) $${RightMem.FlatMem.asmName}\n` freeIfItIsNew(RightMem) return RightMem.asmCode + assemblyCode @@ -202,18 +203,18 @@ export default function assignmentToAsm ( const paddedLong = assertNotUndefined(Right.hexContent).padStart(arraySize * 16, '0') let assemblyCode = '' for (let i = 0; i < arraySize; i++) { - const newLeft = auxVars.getMemoryObjectByLocation(utils.addHexSimple(Left.hexContent, i), operationLine) + const newLeft = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(Left.hexContent, i), operationLine) const newRight = utils.createConstantMemObj( paddedLong.slice(16 * (arraySize - i - 1), 16 * (arraySize - i)) ) - assemblyCode += assignmentToAsm(auxVars, newLeft, newRight, operationLine) + assemblyCode += assignmentToAsm(Program, newLeft, newRight, operationLine) } return assemblyCode } function freeIfItIsNew (FlatObj: FLATTEN_MEMORY_RETURN_OBJECT): void { if (FlatObj.isNew) { - auxVars.freeRegister(FlatObj.FlatMem.address) + Program.Context.freeRegister(FlatObj.FlatMem.address) } } diff --git a/src/codeGenerator/assemblyProcessor/builtinToAsm.ts b/src/codeGenerator/assemblyProcessor/builtinToAsm.ts index a50b32e..0b0d9da 100644 --- a/src/codeGenerator/assemblyProcessor/builtinToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/builtinToAsm.ts @@ -1,13 +1,14 @@ import { assertNotUndefined } from '../../repository/repository' +import { CONTRACT } from '../../typings/contractTypes' import { BUILTIN_TYPES, MEMORY_SLOT, TOKEN } from '../../typings/syntaxTypes' -import { FLATTEN_MEMORY_RETURN_OBJECT, GENCODE_AUXVARS } from '../codeGeneratorTypes' +import { FLATTEN_MEMORY_RETURN_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import { flattenMemory } from './createInstruction' /** Create assembly code for built-in functions */ export function createBuiltinInstruction ( - AstAuxVars: GENCODE_AUXVARS, BuiltinToken: TOKEN, builtinType: BUILTIN_TYPES|undefined, RetMem: MEMORY_SLOT, argsMem: MEMORY_SLOT[] + Program: CONTRACT, BuiltinToken: TOKEN, builtinType: BUILTIN_TYPES|undefined, RetMem: MEMORY_SLOT, argsMem: MEMORY_SLOT[] ) : string { let AuxRegister: MEMORY_SLOT let auxFlatMem: FLATTEN_MEMORY_RETURN_OBJECT @@ -42,7 +43,7 @@ export function createBuiltinInstruction ( function freeAll (tmpArg: FLATTEN_MEMORY_RETURN_OBJECT) { if (tmpArg.isNew) { - AstAuxVars.freeRegister(tmpArg.FlatMem.address) + Program.Context.freeRegister(tmpArg.FlatMem.address) } } @@ -53,65 +54,65 @@ export function createBuiltinInstruction ( switch (BuiltinToken.value) { case 'checkSignature': - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[3], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[4], BuiltinToken.line) + auxFlatMemA = flattenMemory(Program, argsMem[3], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[4], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_A1_A2 $${auxFlatMemA.FlatMem.asmName} $${auxFlatMemB.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[5], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[0], BuiltinToken.line) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) + auxFlatMemA = flattenMemory(Program, argsMem[5], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[0], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_A3 $${auxFlatMemA.FlatMem.asmName}\n` + `FUN set_B2 $${auxFlatMemB.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[1], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[2], BuiltinToken.line) + auxFlatMemA = flattenMemory(Program, argsMem[1], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[2], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_B3_B4 $${auxFlatMemA.FlatMem.asmName} $${auxFlatMemB.FlatMem.asmName}\n` + `FUN @${RetMem.asmName} Check_Sig_B_With_A\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) return assemblyCode case 'distributeToHolders': case 'distributeToHoldersFx': - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[0], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[1], BuiltinToken.line) + auxFlatMemA = flattenMemory(Program, argsMem[0], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[1], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_B1_B2 $${auxFlatMemA.FlatMem.asmName} $${auxFlatMemB.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[2], BuiltinToken.line) + auxFlatMemA = flattenMemory(Program, argsMem[2], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + `FUN set_A1 $${auxFlatMemA.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[3], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[4], BuiltinToken.line) + auxFlatMemA = flattenMemory(Program, argsMem[3], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[4], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_A3_A4 $${auxFlatMemA.FlatMem.asmName} $${auxFlatMemB.FlatMem.asmName}\n` + 'FUN Distribute_To_Asset_Holders\n' - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) return assemblyCode case 'sendQuantityAndAmount': case 'sendQuantityAndAmountFx': - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[3], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[1], BuiltinToken.line) + auxFlatMemA = flattenMemory(Program, argsMem[3], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[1], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_B1_B2 $${auxFlatMemA.FlatMem.asmName} $${auxFlatMemB.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) - auxFlatMemA = flattenMemory(AstAuxVars, argsMem[2], BuiltinToken.line) - auxFlatMemB = flattenMemory(AstAuxVars, argsMem[0], BuiltinToken.line) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) + auxFlatMemA = flattenMemory(Program, argsMem[2], BuiltinToken.line) + auxFlatMemB = flattenMemory(Program, argsMem[0], BuiltinToken.line) assemblyCode += auxFlatMemA.asmCode + auxFlatMemB.asmCode + `FUN set_B3 $${auxFlatMemA.FlatMem.asmName}\n` + `FUN send_to_Address_in_B $${auxFlatMemB.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMemA.FlatMem.address) - AstAuxVars.freeRegister(auxFlatMemB.FlatMem.address) + Program.Context.freeRegister(auxFlatMemA.FlatMem.address) + Program.Context.freeRegister(auxFlatMemB.FlatMem.address) return assemblyCode default: throw new Error('Internal error') @@ -119,8 +120,8 @@ export function createBuiltinInstruction ( } function loopToAsm () : string { - const newJump = '__GNT_' + AstAuxVars.getNewJumpID() - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const newJump = '__GNT_' + Program.Context.getNewJumpID() + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'getNextTx': assemblyCode = 'FUN A_to_Tx_after_Timestamp $_counterTimestamp\n' + @@ -131,13 +132,13 @@ export function createBuiltinInstruction ( break case 'getNextTxFromBlockheight': assemblyCode = tempArgsMem[0].asmCode - if (AstAuxVars.isTemp(tempArgsMem[0].FlatMem.address)) { + if (Program.Context.isTemp(tempArgsMem[0].FlatMem.address)) { AuxRegister = tempArgsMem[0].FlatMem } else { - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() assemblyCode += `SET @${AuxRegister.asmName} $${tempArgsMem[0].FlatMem.asmName}\n` } - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(32), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(32), BuiltinToken.line) assemblyCode += auxFlatMem.asmCode + `SHL @${AuxRegister.asmName} $${auxFlatMem.FlatMem.asmName}\n` + `FUN A_to_Tx_after_Timestamp $${AuxRegister.asmName}\n` + @@ -145,8 +146,8 @@ export function createBuiltinInstruction ( `BZR $${RetMem.asmName} :${newJump}\n` + 'FUN @_counterTimestamp get_Timestamp_for_Tx_in_A\n' + `${newJump}:\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) - AstAuxVars.freeRegister(AuxRegister.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(AuxRegister.address) break default: throw new Error('Internal error') @@ -156,7 +157,7 @@ export function createBuiltinInstruction ( } function specialToAsm () : string { - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'pow': case 'powf': @@ -181,7 +182,7 @@ export function createBuiltinInstruction ( function internalToAsm () : string { let memcopyType : 'SIMPLE' | 'MIXED_LEFT' | 'MIXED_RIGHT' | 'COMPLEX' - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) if (BuiltinToken.value === 'memcopy') { memcopyType = 'COMPLEX' if (argsMem[0].type === 'constant' || argsMem[1].type === 'constant') { @@ -197,26 +198,26 @@ export function createBuiltinInstruction ( case 'SIMPLE': argsMem[0].hexContent = assertNotUndefined(argsMem[0].hexContent) argsMem[1].hexContent = assertNotUndefined(argsMem[1].hexContent) - assemblyCode = `SET @${AstAuxVars.getMemoryObjectByLocation(argsMem[0].hexContent).asmName} $${AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName}\n` + assemblyCode = `SET @${Program.Context.getMemoryObjectByLocation(argsMem[0].hexContent).asmName} $${Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName}\n` break case 'MIXED_LEFT': argsMem[0].hexContent = assertNotUndefined(argsMem[0].hexContent) assemblyCode = tempArgsMem[1].asmCode + - `SET @${AstAuxVars.getMemoryObjectByLocation(argsMem[0].hexContent).asmName} $($${tempArgsMem[1].FlatMem.asmName})\n` + `SET @${Program.Context.getMemoryObjectByLocation(argsMem[0].hexContent).asmName} $($${tempArgsMem[1].FlatMem.asmName})\n` break case 'MIXED_RIGHT': argsMem[1].hexContent = assertNotUndefined(argsMem[1].hexContent) assemblyCode = tempArgsMem[0].asmCode + - `SET @($${tempArgsMem[0].FlatMem.asmName}) $${AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName}\n` + `SET @($${tempArgsMem[0].FlatMem.asmName}) $${Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName}\n` break default: // 'COMPLEX' - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() assemblyCode = tempArgsMem[1].asmCode + tempArgsMem[0].asmCode + `SET @${AuxRegister.asmName} $($${tempArgsMem[1].FlatMem.asmName})\n` + `SET @($${tempArgsMem[0].FlatMem.asmName}) $${AuxRegister.asmName}\n` - AstAuxVars.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegister.address) break } tempArgsMem.forEach(freeAll) @@ -229,10 +230,10 @@ export function createBuiltinInstruction ( switch (BuiltinToken.value) { case 'getCurrentBlockheight': assemblyCode = `FUN @${RetMem.asmName} get_Block_Timestamp\n` - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(32), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(32), BuiltinToken.line) assemblyCode += auxFlatMem.asmCode + `SHR @${RetMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getWeakRandomNumber': assemblyCode = 'FUN Put_Last_Block_GSig_In_A\n' + @@ -246,25 +247,25 @@ export function createBuiltinInstruction ( function receiveToAsm () : string { let AuxRegisterA: MEMORY_SLOT - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'getBlockheight': assemblyCode = tempArgsMem[0].asmCode + `FUN set_A1 $${tempArgsMem[0].FlatMem.asmName}\n` + `FUN @${RetMem.asmName} get_Timestamp_for_Tx_in_A\n` - AstAuxVars.freeRegister(tempArgsMem[0].FlatMem.address) - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(32), BuiltinToken.line) + Program.Context.freeRegister(tempArgsMem[0].FlatMem.address) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(32), BuiltinToken.line) assemblyCode += auxFlatMem.asmCode + `SHR @${RetMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getAmount': case 'getAmountFx': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = tempArgsMem[0].asmCode + auxFlatMem.asmCode + `FUN set_A1_A2 $${tempArgsMem[0].FlatMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` + `FUN @${RetMem.asmName} get_Amount_for_Tx_in_A\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getSender': assemblyCode = tempArgsMem[0].asmCode + @@ -289,10 +290,10 @@ export function createBuiltinInstruction ( 'FUN B_To_Assets_Of_Tx_In_A\n' if (argsMem[1].type === 'constant' || (argsMem[1].type === 'array' && argsMem[1].Offset === undefined)) { argsMem[1].hexContent = assertNotUndefined(argsMem[1].hexContent) - const m1 = AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName - const m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName - const m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 2)).asmName - const m4 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 3)).asmName + const m1 = Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName + const m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName + const m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 2)).asmName + const m4 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 3)).asmName assemblyCode += `FUN @${m1} get_B1\n` + `FUN @${m2} get_B2\n` + @@ -300,15 +301,15 @@ export function createBuiltinInstruction ( `FUN @${m4} get_B4\n` break } - AstAuxVars.freeRegister(tempArgsMem[0].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[0].FlatMem.address) assemblyCode += tempArgsMem[1].asmCode - if (AstAuxVars.isTemp(tempArgsMem[1].FlatMem.address)) { + if (Program.Context.isTemp(tempArgsMem[1].FlatMem.address)) { AuxRegister = tempArgsMem[1].FlatMem } else { - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() assemblyCode += `SET @${AuxRegister.asmName} $${tempArgsMem[1].FlatMem.asmName}\n` } - AuxRegisterA = AstAuxVars.getNewRegister() + AuxRegisterA = Program.Context.getNewRegister() assemblyCode += `FUN @${AuxRegisterA.asmName} get_B1\n` + `SET @($${AuxRegister.asmName}) $${AuxRegisterA.asmName}\n` + @@ -321,8 +322,8 @@ export function createBuiltinInstruction ( `FUN @${AuxRegisterA.asmName} get_B4\n` + `INC @${AuxRegister.asmName}\n` + `SET @($${AuxRegister.asmName}) $${AuxRegisterA.asmName}\n` - AstAuxVars.freeRegister(AuxRegister.address) - AstAuxVars.freeRegister(AuxRegisterA.address) + Program.Context.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegisterA.address) break case 'getQuantity': assemblyCode = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + @@ -337,15 +338,15 @@ export function createBuiltinInstruction ( } function sendToAsm () : string { - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'sendAmount': case 'sendAmountFx': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + auxFlatMem.asmCode + `FUN set_B1_B2 $${tempArgsMem[1].FlatMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` + `FUN send_to_Address_in_B $${tempArgsMem[0].FlatMem.asmName}\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'sendBalance': assemblyCode = tempArgsMem[0].asmCode + @@ -353,7 +354,7 @@ export function createBuiltinInstruction ( 'FUN send_All_to_Address_in_B\n' break case 'sendQuantity': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + tempArgsMem[2].asmCode + auxFlatMem.asmCode + `FUN set_B1_B2 $${tempArgsMem[2].FlatMem.asmName} $${tempArgsMem[1].FlatMem.asmName}\n` + `FUN set_B3 $${auxFlatMem.FlatMem.asmName}\n` + @@ -375,15 +376,15 @@ export function createBuiltinInstruction ( } function contractToAsm () : string { - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'getCreator': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = auxFlatMem.asmCode + `FUN set_B2 $${auxFlatMem.FlatMem.asmName}\n` + 'FUN B_to_Address_of_Creator\n' + `FUN @${RetMem.asmName} get_B1\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getCreatorOf': assemblyCode = tempArgsMem[0].asmCode + @@ -404,11 +405,11 @@ export function createBuiltinInstruction ( break case 'getCurrentBalance': case 'getCurrentBalanceFx': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = auxFlatMem.asmCode + `FUN set_B2 $${auxFlatMem.FlatMem.asmName}\n` + `FUN @${RetMem.asmName} get_Current_Balance\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getAssetBalance': assemblyCode = tempArgsMem[0].asmCode + @@ -423,16 +424,16 @@ export function createBuiltinInstruction ( } function mapsToAsm () : string { - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'getMapValue': case 'getMapValueFx': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + auxFlatMem.asmCode + `FUN set_A1_A2 $${tempArgsMem[0].FlatMem.asmName} $${tempArgsMem[1].FlatMem.asmName}\n` + `FUN set_A3 $${auxFlatMem.FlatMem.asmName}\n` + `FUN @${RetMem.asmName} Get_Map_Value_Keys_In_A\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getExtMapValue': case 'getExtMapValueFx': @@ -456,7 +457,7 @@ export function createBuiltinInstruction ( } function assetsToAsm () : string { - const tempArgsMem = argsMem.map((VarObj) => flattenMemory(AstAuxVars, VarObj, BuiltinToken.line)) + const tempArgsMem = argsMem.map((VarObj) => flattenMemory(Program, VarObj, BuiltinToken.line)) switch (BuiltinToken.value) { case 'issueAsset': assemblyCode = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + tempArgsMem[2].asmCode + @@ -481,11 +482,11 @@ export function createBuiltinInstruction ( break case 'getAccountBalance': case 'getAccountBalanceFx': - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) assemblyCode = tempArgsMem[0].asmCode + auxFlatMem.asmCode + `FUN set_B1_B2 $${tempArgsMem[0].FlatMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` + `FUN @${RetMem.asmName} Get_Account_Balance\n` - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 'getAccountQuantity': assemblyCode = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + @@ -504,14 +505,14 @@ export function createBuiltinInstruction ( retAsm = tempArgsMem[0].asmCode + tempArgsMem[1].asmCode + `FUN set_A1_A2 $${tempArgsMem[0].FlatMem.asmName} $${tempArgsMem[1].FlatMem.asmName}\n` + 'FUN message_from_Tx_in_A_to_B\n' - AstAuxVars.freeRegister(tempArgsMem[0].FlatMem.address) - AstAuxVars.freeRegister(tempArgsMem[1].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[0].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[1].FlatMem.address) if (argsMem[2].type === 'constant' || (argsMem[2].type === 'array' && argsMem[2].Offset === undefined)) { argsMem[2].hexContent = assertNotUndefined(argsMem[2].hexContent) - const m1 = AstAuxVars.getMemoryObjectByLocation(argsMem[2].hexContent).asmName - const m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[2].hexContent, 1)).asmName - const m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[2].hexContent, 2)).asmName - const m4 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[2].hexContent, 3)).asmName + const m1 = Program.Context.getMemoryObjectByLocation(argsMem[2].hexContent).asmName + const m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[2].hexContent, 1)).asmName + const m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[2].hexContent, 2)).asmName + const m4 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[2].hexContent, 3)).asmName return retAsm + `FUN @${m1} get_B1\n` + `FUN @${m2} get_B2\n` + @@ -519,13 +520,13 @@ export function createBuiltinInstruction ( `FUN @${m4} get_B4\n` } assemblyCode += tempArgsMem[2].asmCode - if (AstAuxVars.isTemp(tempArgsMem[2].FlatMem.address)) { + if (Program.Context.isTemp(tempArgsMem[2].FlatMem.address)) { AuxRegister = tempArgsMem[2].FlatMem } else { - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() retAsm += `SET @${AuxRegister.asmName} $${tempArgsMem[2].FlatMem.asmName}\n` } - const AuxRegisterA = AstAuxVars.getNewRegister() + const AuxRegisterA = Program.Context.getNewRegister() retAsm += `FUN @${AuxRegisterA.asmName} get_B1\n` + `SET @($${AuxRegister.asmName}) $${AuxRegisterA.asmName}\n` + @@ -538,8 +539,8 @@ export function createBuiltinInstruction ( `FUN @${AuxRegisterA.asmName} get_B4\n` + `INC @${AuxRegister.asmName}\n` + `SET @($${AuxRegister.asmName}) $${AuxRegisterA.asmName}\n` - AstAuxVars.freeRegister(AuxRegister.address) - AstAuxVars.freeRegister(AuxRegisterA.address) + Program.Context.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegisterA.address) return retAsm } @@ -548,13 +549,13 @@ export function createBuiltinInstruction ( if (argsMem[2].type !== 'constant') { throw new Error(`At line: ${BuiltinToken.line}. Only constants supported for length in 'sendShortMessage'.`) } - AstAuxVars.freeRegister(tempArgsMem[2].FlatMem.address) - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + Program.Context.freeRegister(tempArgsMem[2].FlatMem.address) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) retAsm = tempArgsMem[0].asmCode + auxFlatMem.asmCode + `FUN set_A1_A2 $${tempArgsMem[0].FlatMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` + 'FUN message_from_Tx_in_A_to_B\n' - AstAuxVars.freeRegister(tempArgsMem[0].FlatMem.address) - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(tempArgsMem[0].FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) const len = Number('0x' + argsMem[2].hexContent) if (Number.isNaN(len) || len > 4) { throw new Error(`At line: ${BuiltinToken.line}. Argument 'length' outside range (0 <= length <= 4) in 'readShortMessage'.`) @@ -567,30 +568,30 @@ export function createBuiltinInstruction ( let m1, m2, m3, m4 : string switch (len) { case 1: - m1 = AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName + m1 = Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName retAsm += `FUN @${m1} get_B1\n` break case 2: - m1 = AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName - m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName + m1 = Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName + m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName retAsm += `FUN @${m1} get_B1\n` + `FUN @${m2} get_B2\n` break case 3: - m1 = AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName - m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName - m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 2)).asmName + m1 = Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName + m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName + m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 2)).asmName retAsm += `FUN @${m1} get_B1\n` + `FUN @${m2} get_B2\n` + `FUN @${m3} get_B3\n` break case 4: - m1 = AstAuxVars.getMemoryObjectByLocation(argsMem[1].hexContent).asmName - m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName - m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 2)).asmName - m4 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 3)).asmName + m1 = Program.Context.getMemoryObjectByLocation(argsMem[1].hexContent).asmName + m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 1)).asmName + m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 2)).asmName + m4 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(argsMem[1].hexContent, 3)).asmName retAsm += `FUN @${m1} get_B1\n` + `FUN @${m2} get_B2\n` + @@ -602,20 +603,20 @@ export function createBuiltinInstruction ( retAsm += tempArgsMem[1].asmCode if (len === 1) { // simple case - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() retAsm += `FUN @${AuxRegister.asmName} get_B1\n` + `SET @($${tempArgsMem[1].FlatMem.asmName}) $${AuxRegister.asmName}\n` - AstAuxVars.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegister.address) return retAsm } - if (AstAuxVars.isTemp(tempArgsMem[1].FlatMem.address)) { + if (Program.Context.isTemp(tempArgsMem[1].FlatMem.address)) { AuxRegister = tempArgsMem[1].FlatMem } else { - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() retAsm += `SET @${AuxRegister.asmName} $${tempArgsMem[1].FlatMem.asmName}\n` } - const AuxRegisterA = AstAuxVars.getNewRegister() + const AuxRegisterA = Program.Context.getNewRegister() switch (len) { case 2: retAsm += @@ -650,8 +651,8 @@ export function createBuiltinInstruction ( `INC @${AuxRegister.asmName}\n` + `SET @($${AuxRegister.asmName}) $${AuxRegisterA.asmName}\n` } - AstAuxVars.freeRegister(AuxRegister.address) - AstAuxVars.freeRegister(AuxRegisterA.address) + Program.Context.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegisterA.address) return retAsm } @@ -666,37 +667,37 @@ export function createBuiltinInstruction ( recipientArg = 1 } if (amountArg !== -1) { - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) retAsm = tempArgsMem[amountArg].asmCode + tempArgsMem[recipientArg].asmCode + auxFlatMem.asmCode + `FUN set_B1_B2 $${tempArgsMem[recipientArg].FlatMem.asmName} $${auxFlatMem.FlatMem.asmName}\n` + `FUN send_to_Address_in_B $${tempArgsMem[amountArg].FlatMem.asmName}\n` - AstAuxVars.freeRegister(tempArgsMem[amountArg].FlatMem.address) - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(tempArgsMem[amountArg].FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) } else { retAsm = tempArgsMem[recipientArg].asmCode + `FUN set_B1 $${tempArgsMem[recipientArg].FlatMem.asmName}\n` } - AstAuxVars.freeRegister(tempArgsMem[recipientArg].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[recipientArg].FlatMem.address) if (argsMem[messageArg].type === 'constant' || (argsMem[messageArg].type === 'array' && argsMem[messageArg].Offset === undefined)) { const theHexContent = assertNotUndefined(argsMem[messageArg].hexContent) - const m1 = AstAuxVars.getMemoryObjectByLocation(theHexContent).asmName - const m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName - const m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 2)).asmName - const m4 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 3)).asmName + const m1 = Program.Context.getMemoryObjectByLocation(theHexContent).asmName + const m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName + const m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 2)).asmName + const m4 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 3)).asmName return retAsm + `FUN set_A1_A2 $${m1} $${m2}\n` + `FUN set_A3_A4 $${m3} $${m4}\n` + 'FUN send_A_to_Address_in_B\n' } retAsm += tempArgsMem[messageArg].asmCode - if (AstAuxVars.isTemp(tempArgsMem[messageArg].FlatMem.address)) { + if (Program.Context.isTemp(tempArgsMem[messageArg].FlatMem.address)) { AuxRegister = tempArgsMem[messageArg].FlatMem } else { - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() retAsm += `SET @${AuxRegister.asmName} $${tempArgsMem[messageArg].FlatMem.asmName}\n` } - const AuxRegisterA = AstAuxVars.getNewRegister() - const AuxRegisterB = AstAuxVars.getNewRegister() + const AuxRegisterA = Program.Context.getNewRegister() + const AuxRegisterB = Program.Context.getNewRegister() retAsm += `SET @${AuxRegisterA.asmName} $($${AuxRegister.asmName})\n` + `INC @${AuxRegister.asmName}\n` + @@ -708,9 +709,9 @@ export function createBuiltinInstruction ( `SET @${AuxRegisterB.asmName} $($${AuxRegister.asmName})\n` + `FUN set_A3_A4 $${AuxRegisterA.asmName} $${AuxRegisterB.asmName}\n` + 'FUN send_A_to_Address_in_B\n' - AstAuxVars.freeRegister(AuxRegister.address) - AstAuxVars.freeRegister(AuxRegisterA.address) - AstAuxVars.freeRegister(AuxRegisterB.address) + Program.Context.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegisterA.address) + Program.Context.freeRegister(AuxRegisterB.address) return retAsm } @@ -719,7 +720,7 @@ export function createBuiltinInstruction ( if (argsMem[1].type !== 'constant') { throw new Error(`At line: ${BuiltinToken.line}. Only constants supported for length in 'sendShortMessage'.`) } - AstAuxVars.freeRegister(tempArgsMem[1].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[1].FlatMem.address) const len = Number('0x' + argsMem[1].hexContent) if (Number.isNaN(len) || len > 4) { throw new Error(`At line: ${BuiltinToken.line}. Argument 'length' outside range (0 <= length <= 4) in 'sendShortMessage'.`) @@ -729,43 +730,43 @@ export function createBuiltinInstruction ( } retAsm = tempArgsMem[2].asmCode + `FUN set_B1 $${tempArgsMem[2].FlatMem.asmName}\n` - AstAuxVars.freeRegister(tempArgsMem[2].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[2].FlatMem.address) if (argsMem[0].type === 'constant' || (argsMem[0].type === 'array' && argsMem[0].Offset === undefined)) { let m1, m2, m3, m4 const theHexContent = assertNotUndefined(argsMem[0].hexContent) - AstAuxVars.freeRegister(tempArgsMem[0].FlatMem.address) + Program.Context.freeRegister(tempArgsMem[0].FlatMem.address) switch (len) { case 1: - m1 = AstAuxVars.getMemoryObjectByLocation(theHexContent).asmName + m1 = Program.Context.getMemoryObjectByLocation(theHexContent).asmName retAsm += 'FUN clear_A\n' + `FUN set_A1 $${m1}\n` + 'FUN send_A_to_Address_in_B\n' break case 2: - m1 = AstAuxVars.getMemoryObjectByLocation(theHexContent).asmName - m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName + m1 = Program.Context.getMemoryObjectByLocation(theHexContent).asmName + m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName retAsm += 'FUN clear_A\n' + `FUN set_A1_A2 $${m1} $${m2}\n` + 'FUN send_A_to_Address_in_B\n' break case 3: - m1 = AstAuxVars.getMemoryObjectByLocation(theHexContent).asmName - m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName - m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 2)).asmName - auxFlatMem = flattenMemory(AstAuxVars, utils.createConstantMemObj(0n), BuiltinToken.line) + m1 = Program.Context.getMemoryObjectByLocation(theHexContent).asmName + m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName + m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 2)).asmName + auxFlatMem = flattenMemory(Program, utils.createConstantMemObj(0n), BuiltinToken.line) retAsm += auxFlatMem.asmCode + `FUN set_A1_A2 $${m1} $${m2}\n` + `FUN set_A3_A4 $${m3} $${auxFlatMem.FlatMem.asmName}\n` + 'FUN send_A_to_Address_in_B\n' - AstAuxVars.freeRegister(auxFlatMem.FlatMem.address) + Program.Context.freeRegister(auxFlatMem.FlatMem.address) break case 4: - m1 = AstAuxVars.getMemoryObjectByLocation(theHexContent).asmName - m2 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName - m3 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 2)).asmName - m4 = AstAuxVars.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 3)).asmName + m1 = Program.Context.getMemoryObjectByLocation(theHexContent).asmName + m2 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 1)).asmName + m3 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 2)).asmName + m4 = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(theHexContent, 3)).asmName retAsm += `FUN set_A1_A2 $${m1} $${m2}\n` + `FUN set_A3_A4 $${m3} $${m4}\n` + @@ -776,23 +777,23 @@ export function createBuiltinInstruction ( retAsm += tempArgsMem[0].asmCode if (len === 1) { // simple case - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() retAsm += 'FUN clear_A\n' + `SET @${AuxRegister.asmName} $($${tempArgsMem[0].FlatMem.asmName})\n` + `FUN set_A1 $${AuxRegister.asmName}\n` + 'FUN send_A_to_Address_in_B\n' - AstAuxVars.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegister.address) return retAsm } - if (AstAuxVars.isTemp(tempArgsMem[0].FlatMem.address)) { + if (Program.Context.isTemp(tempArgsMem[0].FlatMem.address)) { AuxRegister = tempArgsMem[0].FlatMem } else { - AuxRegister = AstAuxVars.getNewRegister() + AuxRegister = Program.Context.getNewRegister() retAsm += `SET @${AuxRegister.asmName} $${tempArgsMem[0].FlatMem.asmName}\n` } - const AuxRegisterA = AstAuxVars.getNewRegister() - const AuxRegisterB = AstAuxVars.getNewRegister() + const AuxRegisterA = Program.Context.getNewRegister() + const AuxRegisterB = Program.Context.getNewRegister() switch (len) { case 2: retAsm += @@ -828,9 +829,9 @@ export function createBuiltinInstruction ( `FUN set_A3_A4 $${AuxRegisterA.asmName} $${AuxRegisterB.asmName}\n` + 'FUN send_A_to_Address_in_B\n' } - AstAuxVars.freeRegister(AuxRegister.address) - AstAuxVars.freeRegister(AuxRegisterA.address) - AstAuxVars.freeRegister(AuxRegisterB.address) + Program.Context.freeRegister(AuxRegister.address) + Program.Context.freeRegister(AuxRegisterA.address) + Program.Context.freeRegister(AuxRegisterB.address) return retAsm } diff --git a/src/codeGenerator/assemblyProcessor/comparisionToAsm.ts b/src/codeGenerator/assemblyProcessor/comparisionToAsm.ts index 3ab9d94..3a245e3 100644 --- a/src/codeGenerator/assemblyProcessor/comparisionToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/comparisionToAsm.ts @@ -1,12 +1,12 @@ +import { CONTRACT } from '../../typings/contractTypes' import { TOKEN, MEMORY_SLOT } from '../../typings/syntaxTypes' -import { GENCODE_AUXVARS } from '../codeGeneratorTypes' import { flattenMemory } from './createInstruction' /** Create assembly intructions for comparisions. * @returns the assembly code necessary for branch operations */ export default function comparisionToAsm ( - AuxVars: GENCODE_AUXVARS, OperatorToken: TOKEN, LeftMem: MEMORY_SLOT, RightMem: MEMORY_SLOT, + Program: CONTRACT, OperatorToken: TOKEN, LeftMem: MEMORY_SLOT, RightMem: MEMORY_SLOT, rLogic:boolean, jpFalse: string, jpTrue:string ): string { let assemblyCode = '' @@ -14,30 +14,30 @@ export default function comparisionToAsm ( if (rLogic) { jumpToLabel = jpTrue } - const FlatLeft = flattenMemory(AuxVars, LeftMem, OperatorToken.line) + const FlatLeft = flattenMemory(Program, LeftMem, OperatorToken.line) if (FlatLeft.isNew) { if (LeftMem.Offset?.type === 'variable') { - AuxVars.freeRegister(LeftMem.Offset.addr) + Program.Context.freeRegister(LeftMem.Offset.addr) } - AuxVars.freeRegister(LeftMem.address) + Program.Context.freeRegister(LeftMem.address) } if (RightMem.type === 'constant' && RightMem.hexContent === '0000000000000000' && (OperatorToken.value === '==' || OperatorToken.value === '!=')) { assemblyCode += chooseBranchZero(OperatorToken.value, rLogic) assemblyCode += ` $${FlatLeft.FlatMem.asmName} :${jumpToLabel}\n` if (FlatLeft.isNew === true) { - AuxVars.freeRegister(FlatLeft.FlatMem.address) + Program.Context.freeRegister(FlatLeft.FlatMem.address) } return FlatLeft.asmCode + assemblyCode } - const FlatRight = flattenMemory(AuxVars, RightMem, OperatorToken.line) + const FlatRight = flattenMemory(Program, RightMem, OperatorToken.line) assemblyCode += chooseBranch(OperatorToken.value, rLogic) assemblyCode += ` $${FlatLeft.FlatMem.asmName} $${FlatRight.FlatMem.asmName} :${jumpToLabel}\n` if (FlatLeft.isNew === true) { - AuxVars.freeRegister(FlatLeft.FlatMem.address) + Program.Context.freeRegister(FlatLeft.FlatMem.address) } if (FlatRight.isNew === true) { - AuxVars.freeRegister(FlatRight.FlatMem.address) + Program.Context.freeRegister(FlatRight.FlatMem.address) } return FlatLeft.asmCode + FlatRight.asmCode + assemblyCode } diff --git a/src/codeGenerator/assemblyProcessor/createInstruction.ts b/src/codeGenerator/assemblyProcessor/createInstruction.ts index 466c166..9523d31 100644 --- a/src/codeGenerator/assemblyProcessor/createInstruction.ts +++ b/src/codeGenerator/assemblyProcessor/createInstruction.ts @@ -1,6 +1,7 @@ import { assertExpression, assertNotUndefined } from '../../repository/repository' +import { CONTRACT } from '../../typings/contractTypes' import { MEMORY_SLOT, OFFSET_MODIFIER_CONSTANT, TOKEN } from '../../typings/syntaxTypes' -import { FLATTEN_MEMORY_RETURN_OBJECT, GENCODE_AUXVARS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { FLATTEN_MEMORY_RETURN_OBJECT, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import assignmentToAsm from './assignmentToAsm' @@ -69,21 +70,21 @@ export function createSimpleInstruction (instruction: string, param1: string = ' } export function toRegister ( - AuxVars: GENCODE_AUXVARS, InSolved: GENCODE_SOLVED_OBJECT, line: string + Program: CONTRACT, InSolved: GENCODE_SOLVED_OBJECT, line: string ) : GENCODE_SOLVED_OBJECT { - const retObj = flattenMemory(AuxVars, InSolved.SolvedMem, line) + const retObj = flattenMemory(Program, InSolved.SolvedMem, line) - if (!AuxVars.isTemp(retObj.FlatMem.address)) { + if (!Program.Context.isTemp(retObj.FlatMem.address)) { const inType = utils.getDeclarationFromMemory(InSolved.SolvedMem) - const TmpMemObj = AuxVars.getNewRegister(line) + const TmpMemObj = Program.Context.getNewRegister(line) retObj.asmCode += `SET @${TmpMemObj.asmName} $${retObj.FlatMem.asmName}\n` utils.setMemoryDeclaration(TmpMemObj, inType) - AuxVars.freeRegister(retObj.FlatMem.address) - AuxVars.freeRegister(InSolved.SolvedMem.address) + Program.Context.freeRegister(retObj.FlatMem.address) + Program.Context.freeRegister(InSolved.SolvedMem.address) retObj.FlatMem = TmpMemObj } if (retObj.isNew === true) { - AuxVars.freeRegister(InSolved.SolvedMem.address) + Program.Context.freeRegister(InSolved.SolvedMem.address) } return { SolvedMem: retObj.FlatMem, @@ -93,12 +94,12 @@ export function toRegister ( /** Create assembly code for one api function call */ export function createAPICallInstruction ( - AstAuxVars: GENCODE_AUXVARS, ApiToken: TOKEN, RetMem: MEMORY_SLOT, argsMem: MEMORY_SLOT[] + Program: CONTRACT, ApiToken: TOKEN, RetMem: MEMORY_SLOT, argsMem: MEMORY_SLOT[] ) : string { let assemblyCode = '' const tempArgsMem: MEMORY_SLOT[] = [] argsMem.forEach((VarObj) => { - const Temp = flattenMemory(AstAuxVars, VarObj, '0:0') + const Temp = flattenMemory(Program, VarObj, '0:0') assemblyCode += Temp.asmCode tempArgsMem.push(Temp.FlatMem) }) @@ -110,7 +111,7 @@ export function createAPICallInstruction ( tempArgsMem.forEach(Arg => { assemblyCode += ` $${Arg.asmName}` }) - tempArgsMem.forEach(Arg => AstAuxVars.freeRegister(Arg.address)) + tempArgsMem.forEach(Arg => Program.Context.freeRegister(Arg.address)) return assemblyCode + '\n' } @@ -120,7 +121,7 @@ export function createAPICallInstruction ( * conversion and a boolean to indicate if it is a new object (that must be free later on). */ export function flattenMemory ( - AuxVars: GENCODE_AUXVARS, StuffedMemory: MEMORY_SLOT, line: string + Program: CONTRACT, StuffedMemory: MEMORY_SLOT, line: string ) : FLATTEN_MEMORY_RETURN_OBJECT { const paramDec = utils.getDeclarationFromMemory(StuffedMemory) @@ -142,9 +143,9 @@ export function flattenMemory ( } let RetObj: MEMORY_SLOT if (StuffedMemory.Offset.type === 'variable') { - RetObj = AuxVars.getNewRegister() + RetObj = Program.Context.getNewRegister() RetObj.declaration = paramDec - const offsetVarName = AuxVars.getMemoryObjectByLocation(StuffedMemory.Offset.addr, line).asmName + const offsetVarName = Program.Context.getMemoryObjectByLocation(StuffedMemory.Offset.addr, line).asmName retInstructions += `SET @${RetObj.asmName} $($${StuffedMemory.asmName} + $${offsetVarName})\n` return { FlatMem: RetObj, asmCode: retInstructions, isNew: true } } @@ -154,7 +155,7 @@ export function flattenMemory ( case 'register': case 'long': case 'structRef': - RetObj = AuxVars.getNewRegister() + RetObj = Program.Context.getNewRegister() RetObj.declaration = paramDec if (StuffedMemory.Offset.value === 0) { retInstructions += `SET @${RetObj.asmName} $($${StuffedMemory.asmName})\n` @@ -164,15 +165,15 @@ export function flattenMemory ( retInstructions += FlatConstant.asmCode retInstructions += `SET @${RetObj.asmName} $($${StuffedMemory.asmName} + $${FlatConstant.FlatMem.asmName})\n` if (FlatConstant.isNew) { - AuxVars.freeRegister(FlatConstant.FlatMem.address) + Program.Context.freeRegister(FlatConstant.FlatMem.address) } return { FlatMem: RetObj, asmCode: retInstructions, isNew: true } case 'array': // Looks like an array but can be converted to regular variable - RetObj = AuxVars.getMemoryObjectByLocation( + RetObj = Program.Context.getMemoryObjectByLocation( utils.addHexSimple(StuffedMemory.hexContent, StuffedMemory.Offset.value), line ) - AuxVars.freeRegister(StuffedMemory.address) + Program.Context.freeRegister(StuffedMemory.address) return { FlatMem: RetObj, asmCode: retInstructions, isNew: true } default: throw new Error(`Internal error at line: ${line}. Not implemented type in flattenMemory()`) @@ -180,8 +181,8 @@ export function flattenMemory ( } function flattenConstantWithOffsetConstant (ConstOffset: OFFSET_MODIFIER_CONSTANT) : FLATTEN_MEMORY_RETURN_OBJECT { - const deferencedVar = AuxVars.getMemoryObjectByLocation(utils.addHexSimple(ConstOffset.value, StuffedMemory.hexContent), line) - if (AuxVars.isTemp(deferencedVar.address)) { + const deferencedVar = Program.Context.getMemoryObjectByLocation(utils.addHexSimple(ConstOffset.value, StuffedMemory.hexContent), line) + if (Program.Context.isTemp(deferencedVar.address)) { deferencedVar.declaration = paramDec } return { FlatMem: deferencedVar, asmCode: '', isNew: false } @@ -201,13 +202,13 @@ export function flattenMemory ( if (paramDec === 'fixed') { prefix = 'f' } - const OptMem = AuxVars.memory.find(MEM => { + const OptMem = Program.memory.find(MEM => { return MEM.asmName === prefix + Number('0x' + hexString) && MEM.hexContent === hexString }) if (OptMem) { return { FlatMem: OptMem, asmCode: '', isNew: false } } - const RetObj = AuxVars.getNewRegister() + const RetObj = Program.Context.getNewRegister() RetObj.declaration = paramDec let asmInstruction = '' if (hexString === '0000000000000000') { @@ -222,8 +223,8 @@ export function flattenMemory ( } /** Used in function calls. Mem shall be a memory not stuffed */ -export function forceSetMemFromR0 (AuxVars: GENCODE_AUXVARS, Mem: MEMORY_SLOT, line: string) { - const Temp = flattenMemory(AuxVars, Mem, line) +export function forceSetMemFromR0 (Program: CONTRACT, Mem: MEMORY_SLOT, line: string) { + const Temp = flattenMemory(Program, Mem, line) if (Temp.isNew) { // Debug this, force set should be simple instruction throw new Error('Internal error') @@ -233,26 +234,26 @@ export function forceSetMemFromR0 (AuxVars: GENCODE_AUXVARS, Mem: MEMORY_SLOT, l /** Translate one single instruction from ast to assembly code */ export function createInstruction ( - AuxVars: GENCODE_AUXVARS, OperatorToken: TOKEN, MemParam1?: MEMORY_SLOT, MemParam2?: MEMORY_SLOT, + Program: CONTRACT, OperatorToken: TOKEN, MemParam1?: MEMORY_SLOT, MemParam2?: MEMORY_SLOT, rLogic?:boolean, jpFalse?: string, jpTrue?:string ) : string { switch (OperatorToken.type) { case 'Assignment': return assignmentToAsm( - AuxVars, + Program, assertNotUndefined(MemParam1), assertNotUndefined(MemParam2), OperatorToken.line ) case 'Operator': case 'SetOperator': - return operatorToAsm(AuxVars, OperatorToken, assertNotUndefined(MemParam1), assertNotUndefined(MemParam2)) + return operatorToAsm(Program, OperatorToken, assertNotUndefined(MemParam1), assertNotUndefined(MemParam2)) case 'UnaryOperator': case 'SetUnaryOperator': return unaryOperatorToAsm(OperatorToken, assertNotUndefined(MemParam1)) case 'Comparision': return comparisionToAsm( - AuxVars, + Program, OperatorToken, assertNotUndefined(MemParam1), assertNotUndefined(MemParam2), @@ -261,15 +262,15 @@ export function createInstruction ( assertNotUndefined(jpTrue) ) case 'Push': { - const FlatParam = flattenMemory(AuxVars, assertNotUndefined(MemParam1), OperatorToken.line) + const FlatParam = flattenMemory(Program, assertNotUndefined(MemParam1), OperatorToken.line) FlatParam.asmCode += `PSH $${FlatParam.FlatMem.asmName}\n` if (FlatParam.isNew === true) { - AuxVars.freeRegister(FlatParam.FlatMem.address) + Program.Context.freeRegister(FlatParam.FlatMem.address) } return FlatParam.asmCode } case 'Keyword': - return keywordToAsm(AuxVars, OperatorToken, MemParam1) + return keywordToAsm(Program, OperatorToken, MemParam1) default: throw new Error(`Internal error at line: ${OperatorToken.line}.`) } diff --git a/src/codeGenerator/assemblyProcessor/keywordToAsm.ts b/src/codeGenerator/assemblyProcessor/keywordToAsm.ts index c3e88d2..204d1bf 100644 --- a/src/codeGenerator/assemblyProcessor/keywordToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/keywordToAsm.ts @@ -1,20 +1,21 @@ import { assertNotUndefined } from '../../repository/repository' +import { CONTRACT } from '../../typings/contractTypes' import { TOKEN, MEMORY_SLOT } from '../../typings/syntaxTypes' -import { FLATTEN_MEMORY_RETURN_OBJECT, GENCODE_AUXVARS } from '../codeGeneratorTypes' +import { FLATTEN_MEMORY_RETURN_OBJECT } from '../codeGeneratorTypes' import { flattenMemory } from './createInstruction' /** * Create instruction for keywords asm, break, continue, exit, goto, halt, label, return and sleep. */ export default function keywordToAsm ( - AuxVars: GENCODE_AUXVARS, OperatorToken: TOKEN, FlatMem?: MEMORY_SLOT + Program: CONTRACT, OperatorToken: TOKEN, FlatMem?: MEMORY_SLOT ): string { let TmpMemObj: FLATTEN_MEMORY_RETURN_OBJECT switch (OperatorToken.value) { case 'break': - return `JMP :%generateUtils.getLatestLoopId()%_${OperatorToken.value}\n` + return `JMP :${Program.Context.getLatestLoopID()}_${OperatorToken.value}\n` case 'continue': - return `JMP :%generateUtils.getLatestPureLoopId()%_${OperatorToken.value}\n` + return `JMP :${Program.Context.getLatestPureLoopID()}_${OperatorToken.value}\n` case 'goto': return `JMP :${assertNotUndefined(FlatMem).name}\n` case 'halt': @@ -25,23 +26,23 @@ export default function keywordToAsm ( if (FlatMem === undefined) { return 'RET\n' } - TmpMemObj = flattenMemory(AuxVars, FlatMem, OperatorToken.line) + TmpMemObj = flattenMemory(Program, FlatMem, OperatorToken.line) TmpMemObj.asmCode += `SET @r0 $${TmpMemObj.FlatMem.asmName}\n` TmpMemObj.asmCode += 'RET\n' - AuxVars.freeRegister(FlatMem.address) + Program.Context.freeRegister(FlatMem.address) if (TmpMemObj.isNew === true) { - AuxVars.freeRegister(TmpMemObj.FlatMem.address) + Program.Context.freeRegister(TmpMemObj.FlatMem.address) } return TmpMemObj.asmCode case 'sleep': if (FlatMem === undefined) { return 'SLP\n' } - TmpMemObj = flattenMemory(AuxVars, assertNotUndefined(FlatMem), OperatorToken.line) + TmpMemObj = flattenMemory(Program, assertNotUndefined(FlatMem), OperatorToken.line) TmpMemObj.asmCode += `SLP $${TmpMemObj.FlatMem.asmName}\n` - AuxVars.freeRegister(FlatMem.address) + Program.Context.freeRegister(FlatMem.address) if (TmpMemObj.isNew === true) { - AuxVars.freeRegister(TmpMemObj.FlatMem.address) + Program.Context.freeRegister(TmpMemObj.FlatMem.address) } return TmpMemObj.asmCode case 'asm': { diff --git a/src/codeGenerator/assemblyProcessor/operatorToAsm.ts b/src/codeGenerator/assemblyProcessor/operatorToAsm.ts index a6227c8..5dddcae 100644 --- a/src/codeGenerator/assemblyProcessor/operatorToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/operatorToAsm.ts @@ -1,6 +1,6 @@ import { assertExpression } from '../../repository/repository' +import { CONTRACT } from '../../typings/contractTypes' import { TOKEN, MEMORY_SLOT } from '../../typings/syntaxTypes' -import { GENCODE_AUXVARS } from '../codeGeneratorTypes' import utils from '../utils' import { createInstruction, flattenMemory } from './createInstruction' @@ -9,10 +9,10 @@ import { createInstruction, flattenMemory } from './createInstruction' * @returns the assembly code necessary for the assignment to happen */ export default function operatorToAsm ( - AuxVars: GENCODE_AUXVARS, OperatorToken: TOKEN, LeftMem: MEMORY_SLOT, RightMem: MEMORY_SLOT + Program: CONTRACT, OperatorToken: TOKEN, LeftMem: MEMORY_SLOT, RightMem: MEMORY_SLOT ) : string { - const FlatLeft = flattenMemory(AuxVars, LeftMem, OperatorToken.line) - const FlatRight = flattenMemory(AuxVars, RightMem, OperatorToken.line) + const FlatLeft = flattenMemory(Program, LeftMem, OperatorToken.line) + const FlatRight = flattenMemory(Program, RightMem, OperatorToken.line) function operatorToAsmMain () : string { assertExpression(LeftMem.type !== 'constant') @@ -84,7 +84,7 @@ export default function operatorToAsm ( if (RightMem.type === 'constant') { const optimizationResult = testOptimizations() if (optimizationResult === undefined) { - AuxVars.freeRegister(FlatRight.FlatMem.address) + Program.Context.freeRegister(FlatRight.FlatMem.address) return '' } if (optimizationResult.length > 0) { @@ -125,13 +125,13 @@ export default function operatorToAsm ( case '0000000000000000': return case '0000000000000001': - AuxVars.freeRegister(FlatRight.FlatMem.address) - return createInstruction(AuxVars, utils.genIncToken(), FlatLeft.FlatMem) + Program.Context.freeRegister(FlatRight.FlatMem.address) + return createInstruction(Program, utils.genIncToken(), FlatLeft.FlatMem) case '0000000000000002': - AuxVars.freeRegister(FlatRight.FlatMem.address) - if (!AuxVars.memory.find(MEM => MEM.asmName === 'n2' && MEM.hexContent === '0000000000000002')) { - return createInstruction(AuxVars, utils.genIncToken(), FlatLeft.FlatMem) + - createInstruction(AuxVars, utils.genIncToken(), FlatLeft.FlatMem) + Program.Context.freeRegister(FlatRight.FlatMem.address) + if (!Program.memory.find(MEM => MEM.asmName === 'n2' && MEM.hexContent === '0000000000000002')) { + return createInstruction(Program, utils.genIncToken(), FlatLeft.FlatMem) + + createInstruction(Program, utils.genIncToken(), FlatLeft.FlatMem) } } return '' @@ -142,37 +142,37 @@ export default function operatorToAsm ( return } if (RightMem.hexContent === '0000000000000001') { - AuxVars.freeRegister(FlatRight.FlatMem.address) - return createInstruction(AuxVars, utils.genDecToken(), FlatLeft.FlatMem) + Program.Context.freeRegister(FlatRight.FlatMem.address) + return createInstruction(Program, utils.genDecToken(), FlatLeft.FlatMem) } return '' } function testOptimizationsMultiply () : string|undefined { if (RightMem.hexContent === '0000000000000001') { - AuxVars.freeRegister(FlatRight.FlatMem.address) + Program.Context.freeRegister(FlatRight.FlatMem.address) return } if (RightMem.hexContent === '0000000000000000') { - AuxVars.freeRegister(FlatRight.FlatMem.address) - return createInstruction(AuxVars, utils.genAssignmentToken(OperatorToken.line), FlatLeft.FlatMem, RightMem) + Program.Context.freeRegister(FlatRight.FlatMem.address) + return createInstruction(Program, utils.genAssignmentToken(OperatorToken.line), FlatLeft.FlatMem, RightMem) } return '' } function testOptimizationsDivide () : string|undefined { if (RightMem.hexContent === '0000000000000001') { - AuxVars.freeRegister(FlatRight.FlatMem.address) + Program.Context.freeRegister(FlatRight.FlatMem.address) return } return '' } function returnThisCode (asm : string) : string { - AuxVars.freeRegister(FlatRight.FlatMem.address) + Program.Context.freeRegister(FlatRight.FlatMem.address) if (FlatLeft.isNew === true) { - asm += createInstruction(AuxVars, utils.genAssignmentToken(OperatorToken.line), LeftMem, FlatLeft.FlatMem) - AuxVars.freeRegister(FlatLeft.FlatMem.address) + asm += createInstruction(Program, utils.genAssignmentToken(OperatorToken.line), LeftMem, FlatLeft.FlatMem) + Program.Context.freeRegister(FlatLeft.FlatMem.address) } return FlatLeft.asmCode + FlatRight.asmCode + asm } diff --git a/src/codeGenerator/assemblyProcessor/typeCastingToAsm.ts b/src/codeGenerator/assemblyProcessor/typeCastingToAsm.ts index 78bed74..59f1adc 100644 --- a/src/codeGenerator/assemblyProcessor/typeCastingToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/typeCastingToAsm.ts @@ -1,10 +1,11 @@ +import { CONTRACT } from '../../typings/contractTypes' import { DECLARATION_TYPES } from '../../typings/syntaxTypes' -import { GENCODE_AUXVARS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import { createSimpleInstruction, toRegister } from './createInstruction' export function typeCasting ( - AuxVars: GENCODE_AUXVARS, InSolved: GENCODE_SOLVED_OBJECT, toType: DECLARATION_TYPES, line: string + Program: CONTRACT, InSolved: GENCODE_SOLVED_OBJECT, toType: DECLARATION_TYPES, line: string ) : GENCODE_SOLVED_OBJECT { const fromType = utils.getDeclarationFromMemory(InSolved.SolvedMem) if (fromType === toType) { @@ -15,7 +16,7 @@ export function typeCasting ( switch (toType) { case 'void': // From anything to void - AuxVars.freeRegister(InSolved.SolvedMem.address) + Program.Context.freeRegister(InSolved.SolvedMem.address) InSolved.SolvedMem = utils.createVoidMemObj() return InSolved case 'long': @@ -37,13 +38,13 @@ export function typeCasting ( switch (fromType) { case 'long': // From long to fixed - InSolved = toRegister(AuxVars, InSolved, line) + InSolved = toRegister(Program, InSolved, line) InSolved.asmCode += createSimpleInstruction('LongToFixed', InSolved.SolvedMem.asmName) utils.setMemoryDeclaration(InSolved.SolvedMem, 'fixed') return InSolved case 'void': // From void to fixed - InSolved.SolvedMem = AuxVars.getNewRegister(line) + InSolved.SolvedMem = Program.Context.getNewRegister(line) InSolved.asmCode += `CLR @${InSolved.SolvedMem.asmName}\n` utils.setMemoryDeclaration(InSolved.SolvedMem, 'fixed') return InSolved @@ -62,12 +63,12 @@ export function typeCasting ( switch (fromType) { case 'void': // From void to long - InSolved.SolvedMem = AuxVars.getNewRegister(line) + InSolved.SolvedMem = Program.Context.getNewRegister(line) InSolved.asmCode += `CLR @${InSolved.SolvedMem.asmName}\n` utils.setMemoryDeclaration(InSolved.SolvedMem, 'long') return InSolved case 'fixed': - InSolved = toRegister(AuxVars, InSolved, line) + InSolved = toRegister(Program, InSolved, line) InSolved.asmCode += createSimpleInstruction('FixedToLong', InSolved.SolvedMem.asmName) utils.setMemoryDeclaration(InSolved.SolvedMem, 'long') return InSolved diff --git a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts index ba69dd1..88c5bce 100644 --- a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts @@ -3,7 +3,7 @@ import { CONTRACT } from '../../typings/contractTypes' import { MEMORY_SLOT, DECLARATION_TYPES, BINARY_ASN } from '../../typings/syntaxTypes' import { createSimpleInstruction, createInstruction, setConstAsmCode, toRegister } from '../assemblyProcessor/createInstruction' import { typeCasting } from '../assemblyProcessor/typeCastingToAsm' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import genCode from './genCode' @@ -11,7 +11,7 @@ type SIDES = 'left' | 'right' | 'none' | 'notApplicable' /** Process one binary abstract syntax node */ export default function binaryAsnProcessor ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { let assemblyCode = '' let CurrentNode : BINARY_ASN @@ -38,35 +38,35 @@ export default function binaryAsnProcessor ( throw new Error(`At line: ${CurrentNode.Operation.line}.` + ' It is not possible to evaluate multiple sentences in logical operations.') } - const LGenObj = genCode(Program, AuxVars, { + const LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: false, revLogic: ScopeInfo.revLogic, jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - LGenObj.asmCode += AuxVars.getPostOperations() - const RGenObj = genCode(Program, AuxVars, { + LGenObj.asmCode += Program.Context.SentenceContext.getAndClearPostOperations() + const RGenObj = genCode(Program, { RemAST: CurrentNode.Right, logicalOp: false, revLogic: ScopeInfo.revLogic, jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - RGenObj.asmCode = LGenObj.asmCode + RGenObj.asmCode + AuxVars.getPostOperations() - AuxVars.freeRegister(LGenObj.SolvedMem.address) + RGenObj.asmCode = LGenObj.asmCode + RGenObj.asmCode + Program.Context.SentenceContext.getAndClearPostOperations() + Program.Context.freeRegister(LGenObj.SolvedMem.address) return RGenObj } function operatorProc () : GENCODE_SOLVED_OBJECT { - let LGenObj = genCode(Program, AuxVars, { + let LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: false, revLogic: ScopeInfo.revLogic, jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - let RGenObj = genCode(Program, AuxVars, { + let RGenObj = genCode(Program, { RemAST: CurrentNode.Right, logicalOp: false, revLogic: ScopeInfo.revLogic, @@ -97,7 +97,7 @@ export default function binaryAsnProcessor ( const leftDeclaration = utils.getDeclarationFromMemory(LGenObj.SolvedMem) const rightDeclaration = utils.getDeclarationFromMemory(RGenObj.SolvedMem) // Prepare return object - LGenObj = toRegister(AuxVars, LGenObj, CurrentNode.Operation.line) + LGenObj = toRegister(Program, LGenObj, CurrentNode.Operation.line) // implicit type casting tests and operations if (isPointerAddOrSub(CurrentNode.Operation.value, leftDeclaration, rightDeclaration)) { utils.setMemoryDeclaration(LGenObj.SolvedMem, rightDeclaration) @@ -106,26 +106,26 @@ export default function binaryAsnProcessor ( switch (castSide) { case 'left': if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - AuxVars.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of operator '${CurrentNode.Operation.value}'.`) + Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of operator '${CurrentNode.Operation.value}'.`) } - LGenObj = typeCasting(AuxVars, LGenObj, rightDeclaration, CurrentNode.Operation.line) + LGenObj = typeCasting(Program, LGenObj, rightDeclaration, CurrentNode.Operation.line) break case 'right': { if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - AuxVars.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of operator '${CurrentNode.Operation.value}'.`) + Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of operator '${CurrentNode.Operation.value}'.`) } const oldAsm = RGenObj.asmCode - RGenObj = typeCasting(AuxVars, RGenObj, leftDeclaration, CurrentNode.Operation.line) + RGenObj = typeCasting(Program, RGenObj, leftDeclaration, CurrentNode.Operation.line) // append only the diff LGenObj.asmCode += RGenObj.asmCode.slice(oldAsm.length) } } // Create instruction - LGenObj.asmCode += createInstruction(AuxVars, CurrentNode.Operation, LGenObj.SolvedMem, RGenObj.SolvedMem) + LGenObj.asmCode += createInstruction(Program, CurrentNode.Operation, LGenObj.SolvedMem, RGenObj.SolvedMem) // Handle logical operation if (ScopeInfo.logicalOp === true) { LGenObj.asmCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), LGenObj.SolvedMem, utils.createConstantMemObj(0), @@ -133,39 +133,39 @@ export default function binaryAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(RGenObj.SolvedMem.address) - AuxVars.freeRegister(LGenObj.SolvedMem.address) + Program.Context.freeRegister(RGenObj.SolvedMem.address) + Program.Context.freeRegister(LGenObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: LGenObj.asmCode } } // Return arithmetic result - AuxVars.freeRegister(RGenObj.SolvedMem.address) + Program.Context.freeRegister(RGenObj.SolvedMem.address) return LGenObj } function assignmentProc () : GENCODE_SOLVED_OBJECT { assignmentStartErrorTests() if (CurrentNode.Operation.type === 'Assignment') { - AuxVars.isLeftSideOfAssignment = true + Program.Context.SentenceContext.isLeftSideOfAssignment = true } - AuxVars.hasVoidArray = false - const LGenObj = genCode(Program, AuxVars, { + Program.Context.SentenceContext.hasVoidArray = false + const LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: false, revLogic: ScopeInfo.revLogic, jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - AuxVars.isLeftSideOfAssignment = false + Program.Context.SentenceContext.isLeftSideOfAssignment = false assignmentLeftSideErrorTests(LGenObj.SolvedMem) // Clear isDeclaration before right side evaluation. let savedDeclaration: DECLARATION_TYPES = '' - if (AuxVars.isDeclaration.length !== 0) { - savedDeclaration = AuxVars.isDeclaration - AuxVars.isDeclaration = '' + if (Program.Context.SentenceContext.isDeclaration.length !== 0) { + savedDeclaration = Program.Context.SentenceContext.isDeclaration + Program.Context.SentenceContext.isDeclaration = '' } // Clear register declaration before right side evaluation - const prevStateOfIsRegisterSentence = AuxVars.isRegisterSentence - AuxVars.isRegisterSentence = false + const prevStateOfIsRegisterSentence = Program.Context.SentenceContext.isRegisterSentence + Program.Context.SentenceContext.isRegisterSentence = false // If it is an array item we know, change to the item if (LGenObj.SolvedMem.type === 'array' && LGenObj.SolvedMem.Offset?.type === 'constant') { @@ -173,16 +173,16 @@ export default function binaryAsnProcessor ( throw new Error(`At line ${CurrentNode.Operation.line}. ` + 'Array index is outside array size.') } - LGenObj.SolvedMem = AuxVars.getMemoryObjectByLocation( + LGenObj.SolvedMem = Program.Context.getMemoryObjectByLocation( utils.addHexSimple(LGenObj.SolvedMem.hexContent, LGenObj.SolvedMem.Offset.value) ) } // Get right side gencode object let RGenObj = assignmentRightSideSolver(LGenObj.SolvedMem) // Restore isDeclaration value - AuxVars.isDeclaration = savedDeclaration + Program.Context.SentenceContext.isDeclaration = savedDeclaration // Restore isRegisterSentence value - AuxVars.isRegisterSentence = prevStateOfIsRegisterSentence + Program.Context.SentenceContext.isRegisterSentence = prevStateOfIsRegisterSentence // Error check for Right side if (RGenObj.SolvedMem.type === 'void') { throw new Error(`At line: ${CurrentNode.Operation.line}. ` + @@ -197,14 +197,14 @@ export default function binaryAsnProcessor ( throw new Error('Internal error') case 'right': if (!(lDecl.endsWith('_ptr') && rDecl.endsWith('_ptr'))) { - AuxVars.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of assignment '='.`) + Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of assignment '='.`) } - RGenObj = typeCasting(AuxVars, RGenObj, lDecl, CurrentNode.Operation.line) + RGenObj = typeCasting(Program, RGenObj, lDecl, CurrentNode.Operation.line) } // Create instruction - LGenObj.asmCode += RGenObj.asmCode + createInstruction(AuxVars, CurrentNode.Operation, LGenObj.SolvedMem, RGenObj.SolvedMem) + LGenObj.asmCode += RGenObj.asmCode + createInstruction(Program, CurrentNode.Operation, LGenObj.SolvedMem, RGenObj.SolvedMem) // Process use of 'const' keyword - if (AuxVars.isConstSentence === true) { + if (Program.Context.SentenceContext.isConstSentence === true) { return assignmentConstSolver( LGenObj.SolvedMem, RGenObj.SolvedMem, @@ -212,7 +212,7 @@ export default function binaryAsnProcessor ( CurrentNode.Operation.line ) } - AuxVars.freeRegister(RGenObj.SolvedMem.address) + Program.Context.freeRegister(RGenObj.SolvedMem.address) return LGenObj } @@ -232,7 +232,7 @@ export default function binaryAsnProcessor ( throw new Error(`At line: ${CurrentNode.Operation.line}. ` + `Invalid left value for ${CurrentNode.Operation.type}.`) } - if (Left.type === 'array' && AuxVars.hasVoidArray === false) { + if (Left.type === 'array' && Program.Context.SentenceContext.hasVoidArray === false) { if (Left.Offset === undefined || (Left.Offset.type === 'variable' && Left.Offset.addr === 0 && @@ -242,7 +242,7 @@ export default function binaryAsnProcessor ( `Invalid left value for '${CurrentNode.Operation.type}'. Can not reassign an array.`) } } - if (AuxVars.hasVoidArray && + if (Program.Context.SentenceContext.hasVoidArray && (CurrentNode.Right.type !== 'endASN' || (CurrentNode.Right.type === 'endASN' && CurrentNode.Right.Token.type !== 'Constant'))) { @@ -259,7 +259,7 @@ export default function binaryAsnProcessor ( Left.Offset !== undefined || !utils.findVarNameInAst(Left.name, CurrentNode.Right)) { // Can not reuse assigned var. - return genCode(Program, AuxVars, { + return genCode(Program, { RemAST: CurrentNode.Right, logicalOp: false, revLogic: ScopeInfo.revLogic, @@ -267,15 +267,16 @@ export default function binaryAsnProcessor ( jumpTrue: ScopeInfo.jumpTrue }) } - const registerInitialState = deepCopy(AuxVars.registerInfo) + const registerInitialState = deepCopy(Program.Context.registerInfo) const NewRegister: MEMORY_SLOT = deepCopy(Left) NewRegister.type = 'register' NewRegister.declaration = Left.declaration - AuxVars.registerInfo.unshift({ + Program.Context.registerInfo.unshift({ + endurance: 'Sentence', inUse: false, Template: NewRegister }) - const RetGenObj = genCode(Program, AuxVars, { + const RetGenObj = genCode(Program, { RemAST: CurrentNode.Right, logicalOp: false, revLogic: ScopeInfo.revLogic, @@ -409,7 +410,7 @@ export default function binaryAsnProcessor ( (lDecl.includes('_ptr') && rDecl === 'void_ptr')) { return 'right' } - if (lDecl.includes('ptr') && rDecl === 'long' && AuxVars.hasVoidArray) { + if (lDecl.includes('ptr') && rDecl === 'long' && Program.Context.SentenceContext.hasVoidArray) { return 'none' } throw new Error(`At line ${CurrentNode.Operation.line}. Left and right side of assigment does not match. Types are '${lDecl}' and '${rDecl}'.`) @@ -458,7 +459,7 @@ export default function binaryAsnProcessor ( "Right side of an assigment with 'const' keyword must be a constant.") } // Inspect ASM code and change accordingly - assemblyInstructions = setConstAsmCode(AuxVars.memory, assemblyInstructions, line) + assemblyInstructions = setConstAsmCode(Program.memory, assemblyInstructions, line) return { SolvedMem: Left, asmCode: assemblyInstructions } } @@ -484,7 +485,7 @@ export default function binaryAsnProcessor ( } function logicalToArithmeticOpProc () : GENCODE_SOLVED_OBJECT { - const rnd = AuxVars.getNewJumpID() + const rnd = Program.Context.getNewJumpID() const idCompSF = '__CMP_' + rnd + '_sF' // set false const idCompST = '__CMP_' + rnd + '_sT' // set true const idEnd = '__CMP_' + rnd + '_end' @@ -493,17 +494,17 @@ export default function binaryAsnProcessor ( if (CurrentNode.Operation.value === '||') { swapLogic = true } - let { SolvedMem: RedoAsLogical, asmCode } = genCode(Program, AuxVars, { + let { SolvedMem: RedoAsLogical, asmCode } = genCode(Program, { RemAST: CurrentNode, logicalOp: true, revLogic: swapLogic, jumpFalse: idCompSF, jumpTrue: idCompST }) - const TmpMemObj = AuxVars.getNewRegister() + const TmpMemObj = Program.Context.getNewRegister() asmCode += createSimpleInstruction('Label', swapLogic ? idCompSF : idCompST) asmCode += createInstruction( - AuxVars, + Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, utils.createConstantMemObj(swapLogic ? 0 : 1) @@ -511,20 +512,20 @@ export default function binaryAsnProcessor ( asmCode += createSimpleInstruction('Jump', idEnd) asmCode += createSimpleInstruction('Label', swapLogic ? idCompST : idCompSF) asmCode += createInstruction( - AuxVars, + Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, utils.createConstantMemObj(swapLogic ? 1 : 0) ) asmCode += createSimpleInstruction('Label', idEnd) - AuxVars.freeRegister(RedoAsLogical.address) + Program.Context.freeRegister(RedoAsLogical.address) return { SolvedMem: TmpMemObj, asmCode: asmCode } } function orLogicalOpProc () : GENCODE_SOLVED_OBJECT { - const rnd = AuxVars.getNewJumpID() + const rnd = Program.Context.getNewJumpID() const idNextStmt = '__OR_' + rnd + '_next' - const LGenObj = genCode(Program, AuxVars, { + const LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: true, revLogic: true, @@ -533,7 +534,7 @@ export default function binaryAsnProcessor ( }) assemblyCode += LGenObj.asmCode assemblyCode += createSimpleInstruction('Label', idNextStmt) - const RGenObj = genCode(Program, AuxVars, { + const RGenObj = genCode(Program, { RemAST: CurrentNode.Right, logicalOp: true, revLogic: true, @@ -546,9 +547,9 @@ export default function binaryAsnProcessor ( } function andLogicalOpProc () : GENCODE_SOLVED_OBJECT { - const rnd = AuxVars.getNewJumpID() + const rnd = Program.Context.getNewJumpID() const idNextStmt = '__AND_' + rnd + '_next' - const LGenObj = genCode(Program, AuxVars, { + const LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: true, revLogic: false, @@ -557,7 +558,7 @@ export default function binaryAsnProcessor ( }) assemblyCode += LGenObj.asmCode assemblyCode += createSimpleInstruction('Label', idNextStmt) - const RGenObj = genCode(Program, AuxVars, { + const RGenObj = genCode(Program, { RemAST: CurrentNode.Right, logicalOp: true, revLogic: false, @@ -570,12 +571,12 @@ export default function binaryAsnProcessor ( } function defaultLogicalOpProc () : GENCODE_SOLVED_OBJECT { - let LGenObj = genCode(Program, AuxVars, { + let LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: false, revLogic: ScopeInfo.revLogic }) // ScopeInfo.jumpFalse and ScopeInfo.jumpTrue must be undefined to evaluate expressions - let RGenObj = genCode(Program, AuxVars, { + let RGenObj = genCode(Program, { RemAST: CurrentNode.Right, logicalOp: false, revLogic: ScopeInfo.revLogic @@ -586,19 +587,19 @@ export default function binaryAsnProcessor ( switch (castSide) { case 'left': if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - AuxVars.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of comparision '${CurrentNode.Operation.value}'.`) + Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of comparision '${CurrentNode.Operation.value}'.`) } - LGenObj = typeCasting(AuxVars, LGenObj, rightDeclaration, CurrentNode.Operation.line) + LGenObj = typeCasting(Program, LGenObj, rightDeclaration, CurrentNode.Operation.line) break case 'right': if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - AuxVars.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of comparision '${CurrentNode.Operation.value}'.`) + Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of comparision '${CurrentNode.Operation.value}'.`) } - RGenObj = typeCasting(AuxVars, RGenObj, leftDeclaration, CurrentNode.Operation.line) + RGenObj = typeCasting(Program, RGenObj, leftDeclaration, CurrentNode.Operation.line) } assemblyCode = LGenObj.asmCode + RGenObj.asmCode assemblyCode += createInstruction( - AuxVars, + Program, CurrentNode.Operation, LGenObj.SolvedMem, RGenObj.SolvedMem, @@ -606,8 +607,8 @@ export default function binaryAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(LGenObj.SolvedMem.address) - AuxVars.freeRegister(RGenObj.SolvedMem.address) + Program.Context.freeRegister(LGenObj.SolvedMem.address) + Program.Context.freeRegister(RGenObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: assemblyCode } } @@ -652,7 +653,7 @@ export default function binaryAsnProcessor ( return true } // Try optimization if operation is commutative, right side is register and left side is not - if (AuxVars.isTemp(Right.address) && !AuxVars.isTemp(Left.address)) { + if (Program.Context.isTemp(Right.address) && !Program.Context.isTemp(Left.address)) { return true } // Try optimization if right side is constant, but do not mess if already optimized diff --git a/src/codeGenerator/astProcessor/endAsnProcessor.ts b/src/codeGenerator/astProcessor/endAsnProcessor.ts index 1925f8b..0eaa7c0 100644 --- a/src/codeGenerator/astProcessor/endAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/endAsnProcessor.ts @@ -1,13 +1,13 @@ import { assertNotUndefined } from '../../repository/repository' -import { CONTRACT } from '../../typings/contractTypes' +import { CONTRACT, SC_FUNCTION } from '../../typings/contractTypes' import { END_ASN, LONG_TYPE_DEFINITION, MEMORY_SLOT, STRUCT_TYPE_DEFINITION } from '../../typings/syntaxTypes' import { createSimpleInstruction, createInstruction } from '../assemblyProcessor/createInstruction' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import genCode from './genCode' export default function endAsnProcessor ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { let CurrentNode: END_ASN @@ -53,13 +53,13 @@ export default function endAsnProcessor ( function variableProc () : GENCODE_SOLVED_OBJECT { if (ScopeInfo.logicalOp) { - let { SolvedMem, asmCode } = genCode(Program, AuxVars, { + let { SolvedMem, asmCode } = genCode(Program, { RemAST: CurrentNode, logicalOp: false, revLogic: ScopeInfo.revLogic }) asmCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), SolvedMem, utils.createConstantMemObj(0), @@ -67,29 +67,30 @@ export default function endAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(SolvedMem.address) + Program.Context.freeRegister(SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: asmCode } } - const retMemObj = AuxVars.getMemoryObjectByName( + const retMemObj = Program.Context.getMemoryObjectByName( CurrentNode.Token.value, CurrentNode.Token.line, - AuxVars.isDeclaration + Program.Context.SentenceContext.isDeclaration ) - if (AuxVars.isRegisterSentence) { + if (Program.Context.SentenceContext.isRegisterSentence) { return registerProc(retMemObj) } return { SolvedMem: retMemObj, asmCode: '' } } function registerProc (retMemObj: MEMORY_SLOT) : GENCODE_SOLVED_OBJECT { - const lastFreeRegister = AuxVars.registerInfo.filter(Reg => Reg.inUse === false).reverse()[0] + const lastFreeRegister = Program.Context.registerInfo.filter(Reg => Reg.inUse === false).reverse()[0] if (lastFreeRegister === undefined || lastFreeRegister.Template.asmName === 'r0') { throw new Error(`At line: ${CurrentNode.Token.line}. ` + 'No more registers available. ' + `Increase the number with '#pragma maxAuxVars ${Program.Config.maxAuxVars + 1}' or try to reduce nested operations.`) } lastFreeRegister.inUse = true - AuxVars.scopedRegisters.push(lastFreeRegister.Template.asmName) + lastFreeRegister.endurance = 'Scope' + Program.Context.scopedRegisters.push(lastFreeRegister.Template.asmName) const varPrevAsmName = retMemObj.asmName const motherMemory = assertNotUndefined(Program.memory.find(obj => obj.asmName === retMemObj.asmName), 'Internal error') retMemObj.address = lastFreeRegister.Template.address @@ -103,6 +104,7 @@ export default function endAsnProcessor ( } function keywordProc () : GENCODE_SOLVED_OBJECT { + const CurrentFunction: SC_FUNCTION | undefined = Program.functions[Program.Context.currFunctionIndex] if (ScopeInfo.logicalOp) { throw new Error(`At line: ${CurrentNode.Token.line}. ` + `Cannot use of keyword '${CurrentNode.Token.value}' in logical statements.`) @@ -116,7 +118,7 @@ export default function endAsnProcessor ( case 'sleep': return { SolvedMem: utils.createVoidMemObj(), - asmCode: createInstruction(AuxVars, CurrentNode.Token) + asmCode: createInstruction(Program, CurrentNode.Token) } case 'void': throw new Error(`At line: ${CurrentNode.Token.line}. ` + @@ -134,9 +136,9 @@ export default function endAsnProcessor ( let StructTypeDefinition = Program.typesDefinitions.find( Obj => Obj.type === 'struct' && Obj.name === CurrentNode.Token.extValue ) as STRUCT_TYPE_DEFINITION | undefined - if (StructTypeDefinition === undefined && AuxVars.CurrentFunction !== undefined) { + if (StructTypeDefinition === undefined && CurrentFunction !== undefined) { StructTypeDefinition = Program.typesDefinitions.find( - Obj => Obj.type === 'struct' && Obj.name === AuxVars.CurrentFunction?.name + '_' + CurrentNode.Token.extValue + Obj => Obj.type === 'struct' && Obj.name === CurrentFunction?.name + '_' + CurrentNode.Token.extValue ) as STRUCT_TYPE_DEFINITION | undefined } if (StructTypeDefinition === undefined) { @@ -150,16 +152,16 @@ export default function endAsnProcessor ( } case 'return': // this is 'return;' - if (AuxVars.CurrentFunction === undefined) { + if (CurrentFunction === undefined) { throw new Error(`At line: ${CurrentNode.Token.line}.` + " Can not use 'return' in global statements.") } - if (AuxVars.CurrentFunction.declaration !== 'void') { + if (CurrentFunction.declaration !== 'void') { throw new Error(`At line: ${CurrentNode.Token.line}.` + - ` Function '${AuxVars.CurrentFunction.name}'` + - ` must return a '${AuxVars.CurrentFunction.declaration}' value.`) + ` Function '${CurrentFunction.name}'` + + ` must return a '${CurrentFunction.declaration}' value.`) } - if (AuxVars.CurrentFunction.name === 'main' || AuxVars.CurrentFunction.name === 'catch') { + if (CurrentFunction.name === 'main' || CurrentFunction.name === 'catch') { return { SolvedMem: utils.createVoidMemObj(), asmCode: createSimpleInstruction('exit') @@ -167,7 +169,7 @@ export default function endAsnProcessor ( } return { SolvedMem: utils.createVoidMemObj(), - asmCode: createInstruction(AuxVars, CurrentNode.Token) + asmCode: createInstruction(Program, CurrentNode.Token) } default: throw new Error(`Internal error at line: ${CurrentNode.Token.line}.`) diff --git a/src/codeGenerator/astProcessor/exceptionAsnProcessor.ts b/src/codeGenerator/astProcessor/exceptionAsnProcessor.ts index 3d68fd3..9dcadad 100644 --- a/src/codeGenerator/astProcessor/exceptionAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/exceptionAsnProcessor.ts @@ -1,12 +1,12 @@ import { assertNotUndefined } from '../../repository/repository' import { CONTRACT } from '../../typings/contractTypes' import { createInstruction } from '../assemblyProcessor/createInstruction' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import genCode from './genCode' export default function exceptionAsnProcessor ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { const CurrentNode = utils.assertAsnType('exceptionASN', ScopeInfo.RemAST) if (ScopeInfo.jumpFalse !== undefined) { @@ -14,23 +14,23 @@ export default function exceptionAsnProcessor ( ' Can not use SetUnaryOperator (++ or --) during logical operations with branches') } if (CurrentNode.Left !== undefined) { - const LGenObj = genCode(Program, AuxVars, { + const LGenObj = genCode(Program, { RemAST: CurrentNode.Left, logicalOp: false, revLogic: ScopeInfo.revLogic, jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - LGenObj.asmCode += createInstruction(AuxVars, CurrentNode.Operation, LGenObj.SolvedMem) + LGenObj.asmCode += createInstruction(Program, CurrentNode.Operation, LGenObj.SolvedMem) return LGenObj } - const RGenObj = genCode(Program, AuxVars, { + const RGenObj = genCode(Program, { RemAST: assertNotUndefined(CurrentNode.Right), logicalOp: false, revLogic: ScopeInfo.revLogic, jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - AuxVars.postOperations += createInstruction(AuxVars, CurrentNode.Operation, RGenObj.SolvedMem) + Program.Context.SentenceContext.postOperations += createInstruction(Program, CurrentNode.Operation, RGenObj.SolvedMem) return RGenObj } diff --git a/src/codeGenerator/astProcessor/functionSolver.ts b/src/codeGenerator/astProcessor/functionSolver.ts index fc7d797..69617a6 100644 --- a/src/codeGenerator/astProcessor/functionSolver.ts +++ b/src/codeGenerator/astProcessor/functionSolver.ts @@ -5,12 +5,12 @@ import { createBuiltinInstruction } from '../assemblyProcessor/builtinToAsm' import { createSimpleInstruction, createInstruction, createAPICallInstruction, forceSetMemFromR0 } from '../assemblyProcessor/createInstruction' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import genCode from './genCode' export default function functionSolver ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { let CurrentNode: LOOKUP_ASN @@ -39,15 +39,15 @@ export default function functionSolver ( let returnAssemblyCode = '' // It is regular function call let isRecursive = false - if (FunctionToCall.name === AuxVars.CurrentFunction?.name) { + if (Program.Context.currFunctionIndex !== -1 && FunctionToCall.name === Program.functions[Program.Context.currFunctionIndex].name) { isRecursive = true // stack current scope variables - AuxVars.memory.filter(OBJ => OBJ.scope === FunctionToCall.name && OBJ.address > 0).reverse().forEach(MEM => { + Program.memory.filter(OBJ => OBJ.scope === FunctionToCall.name && OBJ.address > 0).reverse().forEach(MEM => { returnAssemblyCode += createSimpleInstruction('Push', MEM.asmName) }) } // Save registers currently in use in stack. Function execution will overwrite them - const registerStack = AuxVars.registerInfo.filter(OBJ => OBJ.inUse === true).reverse() + const registerStack = Program.Context.registerInfo.filter(OBJ => OBJ.inUse === true).reverse() registerStack.forEach(OBJ => { returnAssemblyCode += createSimpleInstruction('Push', OBJ.Template.asmName) }) @@ -62,7 +62,7 @@ export default function functionSolver ( } // Push arguments into stack for (let i = rawArgs.length - 1; i >= 0; i--) { - const ArgGenObj = genCode(Program, AuxVars, { + const ArgGenObj = genCode(Program, { RemAST: rawArgs[i], logicalOp: false, revLogic: false @@ -79,12 +79,12 @@ export default function functionSolver ( } returnAssemblyCode += ArgGenObj.asmCode returnAssemblyCode += createInstruction( - AuxVars, + Program, utils.genAssignmentToken(CurrentNode.Token.line), fnArg, ArgGenObj.SolvedMem ) - AuxVars.freeRegister(ArgGenObj.SolvedMem.address) + Program.Context.freeRegister(ArgGenObj.SolvedMem.address) } // Create instruction if (FunctionToCall.isInline) { @@ -96,10 +96,10 @@ export default function functionSolver ( if (FunctionToCall.declaration === 'void') { FnRetObj = utils.createVoidMemObj() } else { - FnRetObj = AuxVars.getNewRegister() + FnRetObj = Program.Context.getNewRegister() FnRetObj.declaration = FunctionToCall.declaration FnRetObj.typeDefinition = FunctionToCall.typeDefinition - returnAssemblyCode += forceSetMemFromR0(AuxVars, FnRetObj, CurrentNode.Token.line) + returnAssemblyCode += forceSetMemFromR0(Program, FnRetObj, CurrentNode.Token.line) } // Load registers again registerStack.reverse() @@ -108,7 +108,7 @@ export default function functionSolver ( }) if (isRecursive) { // unstack current scope variables - AuxVars.memory.filter(OBJ => OBJ.scope === FunctionToCall.name && OBJ.address > 0).forEach(MEM => { + Program.memory.filter(OBJ => OBJ.scope === FunctionToCall.name && OBJ.address > 0).forEach(MEM => { returnAssemblyCode += createSimpleInstruction('Pop', MEM.asmName) }) } @@ -122,7 +122,7 @@ export default function functionSolver ( if (ifnToCall.declaration === 'void' || ifnToCall.name === 'bcftol' || ifnToCall.name === 'bcltof') { FnRetObj = utils.createVoidMemObj() } else { - FnRetObj = AuxVars.getNewRegister() // reserve tempvar for return type + FnRetObj = Program.Context.getNewRegister() // reserve tempvar for return type FnRetObj.declaration = ifnToCall.declaration } if (rawArgs[0].type === 'nullASN') { @@ -134,7 +134,7 @@ export default function functionSolver ( ` It must have '${ifnToCall.argsMemObj.length}' args.`) } rawArgs.forEach((RawSentence, idx) => { - const ArgGenObj = genCode(Program, AuxVars, { + const ArgGenObj = genCode(Program, { RemAST: RawSentence, logicalOp: false, revLogic: false @@ -153,7 +153,7 @@ export default function functionSolver ( }) if (type === 'api') { returnAssemblyCode += createAPICallInstruction( - AuxVars, + Program, utils.genAPICallToken(CurrentNode.Token.line, ifnToCall.asmName), FnRetObj, processedArgs @@ -164,14 +164,14 @@ export default function functionSolver ( return { SolvedMem: processedArgs[0], asmCode: returnAssemblyCode } } returnAssemblyCode += createBuiltinInstruction( - AuxVars, + Program, utils.genBuiltInToken(CurrentNode.Token.line, ifnToCall.asmName), ifnToCall.builtin, FnRetObj, processedArgs ) } - processedArgs.forEach(varnm => AuxVars.freeRegister(varnm.address)) + processedArgs.forEach(varnm => Program.Context.freeRegister(varnm.address)) return { SolvedMem: FnRetObj, asmCode: returnAssemblyCode } } return functionSolverMain() diff --git a/src/codeGenerator/astProcessor/genCode.ts b/src/codeGenerator/astProcessor/genCode.ts index 7054bc9..9f29947 100644 --- a/src/codeGenerator/astProcessor/genCode.ts +++ b/src/codeGenerator/astProcessor/genCode.ts @@ -1,5 +1,5 @@ import { CONTRACT } from '../../typings/contractTypes' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import binaryAsnProcessor from './binaryAsnProcessor' @@ -11,22 +11,22 @@ import unaryAsnProcessor from './unaryAsnProcessor' /** Manages the functions to process Abstract Syntax Nodes */ export default function genCode ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { switch (ScopeInfo.RemAST.type) { case 'nullASN': return { SolvedMem: utils.createVoidMemObj(), asmCode: '' } case 'endASN': - return endAsnProcessor(Program, AuxVars, ScopeInfo) + return endAsnProcessor(Program, ScopeInfo) case 'lookupASN': - return lookupAsnProcessor(Program, AuxVars, ScopeInfo) + return lookupAsnProcessor(Program, ScopeInfo) case 'unaryASN': - return unaryAsnProcessor(Program, AuxVars, ScopeInfo) + return unaryAsnProcessor(Program, ScopeInfo) case 'exceptionASN': - return exceptionAsnProcessor(Program, AuxVars, ScopeInfo) + return exceptionAsnProcessor(Program, ScopeInfo) case 'binaryASN': - return binaryAsnProcessor(Program, AuxVars, ScopeInfo) + return binaryAsnProcessor(Program, ScopeInfo) case 'switchASN': - return switchAsnProcessor(Program, AuxVars, ScopeInfo) + return switchAsnProcessor(Program, ScopeInfo) } } diff --git a/src/codeGenerator/astProcessor/lookupAsnProcessor.ts b/src/codeGenerator/astProcessor/lookupAsnProcessor.ts index 10f0662..8d1ff02 100644 --- a/src/codeGenerator/astProcessor/lookupAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/lookupAsnProcessor.ts @@ -4,13 +4,13 @@ import { MEMORY_SLOT, ARRAY_TYPE_DEFINITION, STRUCT_TYPE_DEFINITION, DECLARATION_TYPES, LOOKUP_ASN, TOKEN_MODIFIER, TOKEN_MODIFIER_ARRAY, TOKEN_MODIFIER_MEMBER } from '../../typings/syntaxTypes' import { createInstruction } from '../assemblyProcessor/createInstruction' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import functionSolver from './functionSolver' import genCode from './genCode' export default function lookupAsnProcessor ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { let arrayIndex = -1 let CurrentNode: LOOKUP_ASN @@ -21,16 +21,16 @@ export default function lookupAsnProcessor ( switch (CurrentNode.Token.type) { case 'Variable': StartObj = { - SolvedMem: AuxVars.getMemoryObjectByName( + SolvedMem: Program.Context.getMemoryObjectByName( CurrentNode.Token.value, CurrentNode.Token.line, - AuxVars.isDeclaration + Program.Context.SentenceContext.isDeclaration ), asmCode: '' } break case 'Function': - StartObj = functionSolver(Program, AuxVars, ScopeInfo) + StartObj = functionSolver(Program, ScopeInfo) break default: throw new Error(`Internal error at line: ${CurrentNode.Token.line}.`) @@ -46,7 +46,7 @@ export default function lookupAsnProcessor ( ' Function returning void value can not be used in conditionals decision.') } EndObj.asmCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), EndObj.SolvedMem, utils.createConstantMemObj(0), @@ -54,7 +54,7 @@ export default function lookupAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(EndObj.SolvedMem.address) + Program.Context.freeRegister(EndObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: EndObj.asmCode } } return EndObj @@ -112,11 +112,11 @@ export default function lookupAsnProcessor ( } if (Previous.SolvedMem.Offset.type === 'constant') { // Deference location and continue - const TmpMemObj = AuxVars.getNewRegister() + const TmpMemObj = Program.Context.getNewRegister() TmpMemObj.declaration = Previous.SolvedMem.Offset.declaration TmpMemObj.typeDefinition = Previous.SolvedMem.Offset.typeDefinition Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, Previous.SolvedMem @@ -141,18 +141,18 @@ export default function lookupAsnProcessor ( " Using wrong member notation. Try to use '->' instead.") } if (Previous.SolvedMem.Offset === undefined) { - Previous.SolvedMem = AuxVars.getMemoryObjectByLocation(Number('0x' + Previous.SolvedMem.hexContent) + + Previous.SolvedMem = Program.Context.getMemoryObjectByLocation(Number('0x' + Previous.SolvedMem.hexContent) + TypeD.structAccumulatedSize[memberIdx][1], memberLine) return Previous } if (Previous.SolvedMem.Offset.type === 'constant') { const newLoc = Previous.SolvedMem.Offset.value + Number('0x' + Previous.SolvedMem.hexContent) - Previous.SolvedMem = AuxVars.getMemoryObjectByLocation(newLoc + TypeD.structAccumulatedSize[memberIdx][1], memberLine) + Previous.SolvedMem = Program.Context.getMemoryObjectByLocation(newLoc + TypeD.structAccumulatedSize[memberIdx][1], memberLine) return Previous } // finally Previous.MemObj.offset_type is "variable" - Previous.asmCode += createInstruction(AuxVars, utils.genAddToken(memberLine), - AuxVars.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, memberLine), + Previous.asmCode += createInstruction(Program, utils.genAddToken(memberLine), + Program.Context.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, memberLine), utils.createConstantMemObj(memOffset + TypeD.structAccumulatedSize[memberIdx][1])) Previous.SolvedMem.Offset.declaration = MembersDefinitions.declaration Previous.SolvedMem.Offset.typeDefinition = MembersDefinitions.typeDefinition @@ -167,9 +167,9 @@ export default function lookupAsnProcessor ( } const len = assertNotUndefined(TypeD.MemoryTemplate.ArrayItem?.totalSize) if (Memory.Offset?.type === 'variable') { - AuxVars.freeRegister(Memory.Offset.addr) + Program.Context.freeRegister(Memory.Offset.addr) } - AuxVars.freeRegister(Memory.address) + Program.Context.freeRegister(Memory.address) return { SolvedMem: utils.createConstantMemObj((len - 1) / TypeD.MemoryTemplate.size), asmCode: '' @@ -225,26 +225,26 @@ export default function lookupAsnProcessor ( } } // Solve array parameter AST - const ParamMemObj = genCode(Program, AuxVars, { + const ParamMemObj = genCode(Program, { RemAST: CurrentModifier.Center, logicalOp: false, revLogic: false }) if (ParamMemObj.SolvedMem.Offset) { // Need to deference array index... - const TmpMemObj = AuxVars.getNewRegister() + const TmpMemObj = Program.Context.getNewRegister() TmpMemObj.declaration = utils.getDeclarationFromMemory(ParamMemObj.SolvedMem) - ParamMemObj.asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, ParamMemObj.SolvedMem) + ParamMemObj.asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, ParamMemObj.SolvedMem) if (ParamMemObj.SolvedMem.Offset.type === 'variable') { - AuxVars.freeRegister(ParamMemObj.SolvedMem.Offset.addr) + Program.Context.freeRegister(ParamMemObj.SolvedMem.Offset.addr) } - AuxVars.freeRegister(ParamMemObj.SolvedMem.address) + Program.Context.freeRegister(ParamMemObj.SolvedMem.address) ParamMemObj.SolvedMem = TmpMemObj } Previous.asmCode += ParamMemObj.asmCode // special case for left side void array multi long assignment if (ParamMemObj.SolvedMem.type === 'void') { - AuxVars.hasVoidArray = true + Program.Context.SentenceContext.hasVoidArray = true return Previous } // big decision tree depending on Previous.MemObj.Offset.value and ParamMemObj.address @@ -256,7 +256,7 @@ export default function lookupAsnProcessor ( } Previous.SolvedMem.Offset.declaration = Previous.SolvedMem.ArrayItem.declaration Previous.SolvedMem.Offset.typeDefinition = Previous.SolvedMem.ArrayItem.typeDefinition - if (AuxVars.isTemp(Previous.SolvedMem.Offset.addr)) { + if (Program.Context.isTemp(Previous.SolvedMem.Offset.addr)) { return arrProcOffsetRegister(Previous, ParamMemObj.SolvedMem, multiplier) } // Finally Previous.MemObj.Offset.addr is variable and not register @@ -317,7 +317,7 @@ export default function lookupAsnProcessor ( typeDefinition: Previous.SolvedMem.ArrayItem.typeDefinition } Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genMulToken(CurrentNode.Token.line), Param, utils.createConstantMemObj(multiplier) @@ -333,11 +333,11 @@ export default function lookupAsnProcessor ( } return Previous } - TmpMemObj = AuxVars.getNewRegister() + TmpMemObj = Program.Context.getNewRegister() Previous.asmCode += createInstruction( - AuxVars, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, utils.createConstantMemObj(multiplier) + Program, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, utils.createConstantMemObj(multiplier) ) - Previous.asmCode += createInstruction(AuxVars, utils.genMulToken(CurrentNode.Token.line), TmpMemObj, Param) + Previous.asmCode += createInstruction(Program, utils.genMulToken(CurrentNode.Token.line), TmpMemObj, Param) Previous.SolvedMem.Offset = { type: 'variable', addr: TmpMemObj.address, @@ -364,13 +364,13 @@ export default function lookupAsnProcessor ( return Previous case 'register': Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genMulToken(CurrentNode.Token.line), Param, utils.createConstantMemObj(multiplier) ) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(CurrentNode.Token.line), Param, utils.createConstantMemObj(Previous.SolvedMem.Offset.value) @@ -392,16 +392,16 @@ export default function lookupAsnProcessor ( } return Previous } - TmpMemObj = AuxVars.getNewRegister() - Previous.asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, Param) + TmpMemObj = Program.Context.getNewRegister() + Previous.asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, Param) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genMulToken(CurrentNode.Token.line), TmpMemObj, utils.createConstantMemObj(multiplier) ) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(CurrentNode.Token.line), TmpMemObj, utils.createConstantMemObj(Previous.SolvedMem.Offset.value) @@ -428,53 +428,53 @@ export default function lookupAsnProcessor ( case 'constant': { multiplier *= Number('0x' + Param.hexContent) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(CurrentNode.Token.line), - AuxVars.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), + Program.Context.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), utils.createConstantMemObj(multiplier) ) return Previous } case 'register': Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genMulToken(CurrentNode.Token.line), Param, utils.createConstantMemObj(multiplier) ) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(CurrentNode.Token.line), - AuxVars.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), + Program.Context.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), Param ) - AuxVars.freeRegister(Param.address) + Program.Context.freeRegister(Param.address) return Previous case 'regularVariable': if (multiplier === 1) { Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(CurrentNode.Token.line), - AuxVars.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), + Program.Context.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), Param ) return Previous } - TmpMemObj = AuxVars.getNewRegister() - Previous.asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, Param) + TmpMemObj = Program.Context.getNewRegister() + Previous.asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Token.line), TmpMemObj, Param) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genMulToken(CurrentNode.Token.line), TmpMemObj, utils.createConstantMemObj(multiplier) ) Previous.asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(CurrentNode.Token.line), - AuxVars.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), + Program.Context.getMemoryObjectByLocation(Previous.SolvedMem.Offset.addr, CurrentNode.Token.line), TmpMemObj ) - AuxVars.freeRegister(TmpMemObj.address) + Program.Context.freeRegister(TmpMemObj.address) return Previous } } @@ -483,7 +483,7 @@ export default function lookupAsnProcessor ( if (loc === -1) { return 'constant' } - if (AuxVars.isTemp(loc)) { + if (Program.Context.isTemp(loc)) { return 'register' } return 'regularVariable' diff --git a/src/codeGenerator/astProcessor/setupGenCode.ts b/src/codeGenerator/astProcessor/setupGenCode.ts deleted file mode 100644 index 1115aa8..0000000 --- a/src/codeGenerator/astProcessor/setupGenCode.ts +++ /dev/null @@ -1,190 +0,0 @@ -import { assertNotUndefined, deepCopy } from '../../repository/repository' -import { AST, MEMORY_SLOT, DECLARATION_TYPES } from '../../typings/syntaxTypes' -import { GLOBAL_AUXVARS, SETUPGENCODE_ARGS, GENCODE_AUXVARS } from '../codeGeneratorTypes' -import genCode from './genCode' - -/** Translates global variables to scope auxvars to be used by genCode. - * Also handles return value with some tests, alterations and optimizations. */ -export default function setupGenCode ( - Globals: GLOBAL_AUXVARS, CodeGenInfo: SETUPGENCODE_ARGS, sentenceLine: string -) : string { - const AuxVars: GENCODE_AUXVARS = { - CurrentFunction: Globals.Program.functions[Globals.currFunctionIndex], - memory: Globals.Program.memory, - jumpId: Globals.jumpId, - registerInfo: [], - postOperations: '', - isDeclaration: '', - isLeftSideOfAssignment: false, - isConstSentence: false, - isRegisterSentence: false, - hasVoidArray: false, - scopedRegisters: Globals.scopedRegisters, - warnings: [], - isTemp: auxvarsIsTemp, - getNewRegister: auxvarsGetNewRegister, - freeRegister: auxvarsFreeRegister, - getPostOperations: auxvarsGetPostOperations, - getMemoryObjectByName: auxvarsGetMemoryObjectByName, - getMemoryObjectByLocation: auxvarsGetMemoryObjectByLocation, - getNewJumpID: auxvarsGetNewJumpID - } - - function setupGenCodeMain (): string { - CodeGenInfo.InitialAST = assertNotUndefined(CodeGenInfo.InitialAST) - CodeGenInfo.initialIsReversedLogic = CodeGenInfo.initialIsReversedLogic ?? false - // Create registers array - AuxVars.memory.filter(OBJ => /^r\d$/.test(OBJ.asmName) && OBJ.type === 'register').forEach(MEM => { - AuxVars.registerInfo.push({ - inUse: false, - Template: MEM - }) - }) - // Mark in use registers (keyword 'register') - AuxVars.registerInfo.forEach(Mem => { - if (AuxVars.scopedRegisters.find(item => item === Mem.Template.asmName)) { - Mem.inUse = true - } - }) - const code = genCode(Globals.Program, AuxVars, { - RemAST: CodeGenInfo.InitialAST, - logicalOp: CodeGenInfo.initialJumpTarget !== undefined, - revLogic: CodeGenInfo.initialIsReversedLogic, - jumpFalse: CodeGenInfo.initialJumpTarget, - jumpTrue: CodeGenInfo.initialJumpNotTarget - }) - validateReturnedVariable(CodeGenInfo.InitialAST, code.SolvedMem) - code.asmCode += AuxVars.postOperations - Globals.jumpId = AuxVars.jumpId - Globals.Program.warnings.push(...AuxVars.warnings) - // Check throw conditions that were out-of-scope - const analysyCode = code.asmCode.split('\n') - code.asmCode = analysyCode.map(line => { - if (line.includes('%generateUtils.getLatestLoopId()%')) { - return line.replace('%generateUtils.getLatestLoopId()%', Globals.getLatestLoopID()) - } - if (line.includes('%generateUtils.getLatestPureLoopId()%')) { - return line.replace('%generateUtils.getLatestPureLoopId()%', Globals.getLatestPureLoopID()) - } - return line - }).join('\n') - return code.asmCode - } - - function validateReturnedVariable (InitAST: AST, RetObj: MEMORY_SLOT) { - if (CodeGenInfo.initialJumpTarget === undefined && - RetObj.type === 'register') { - if ((InitAST.type === 'unaryASN' && InitAST.Operation.value !== '*') || - (InitAST.type === 'binaryASN' && - (InitAST.Operation.type === 'Comparision' || InitAST.Operation.type === 'Operator'))) { - throw new Error(`At line: ${InitAST.Operation.line}. ` + - 'Operation returning a value that is not being used. Use casting to (void) to avoid this error.') - } - } - } - - function auxvarsIsTemp (loc: number) : boolean { - if (loc === -1) return false - const id = AuxVars.registerInfo.find(OBJ => OBJ.Template.address === loc) - if (id === undefined) { - return false - } - if (AuxVars.scopedRegisters.find(items => items === id.Template.asmName)) { - // It is a register, but scoped. Do not mess!!! - return false - } - return true - } - - function auxvarsGetNewRegister (line: string = sentenceLine): MEMORY_SLOT { - const id = AuxVars.registerInfo.find(OBJ => OBJ.inUse === false) - if (id === undefined) { - throw new Error(`At line: ${line}. ` + - 'No more registers available. ' + - `Increase the number with '#pragma maxAuxVars ${Globals.Program.Config.maxAuxVars + 1}' or try to reduce nested operations.`) - } - id.inUse = true - return deepCopy(id.Template) - } - - function auxvarsFreeRegister (loc: number|undefined): void { - if (loc === undefined || loc === -1) { - return - } - const id = AuxVars.registerInfo.find(OBJ => OBJ.Template.address === loc) - if (id === undefined) return - id.inUse = false - } - - function auxvarsGetPostOperations (): string { - const ret = AuxVars.postOperations - AuxVars.postOperations = '' - return ret - } - - function auxvarsGetMemoryObjectByName ( - varName: string, line: string = sentenceLine, varDeclaration: DECLARATION_TYPES = '' - ) : MEMORY_SLOT { - let MemFound: MEMORY_SLOT | undefined - if (AuxVars.CurrentFunction !== undefined) { // find function scope variable - MemFound = AuxVars.memory.find(obj => { - return obj.name === varName && obj.scope === AuxVars.CurrentFunction?.name - }) - } - if (MemFound === undefined) { - // do a global scope search - MemFound = AuxVars.memory.find(obj => obj.name === varName && obj.scope === '') - } - if (MemFound === undefined) { - throw new Error(`At line: ${line}. Using variable '${varName}' before declaration.`) - } - if (MemFound.toBeRegister && MemFound.asmName === '') { - throw new Error(`At line: ${line}. Using variable '${varName}' out of scope!`) - } - if (!MemFound.isSet) { - detectAndSetNotInitialized(MemFound, line, varDeclaration !== '') - } - if (varDeclaration !== '') { // we are in declarations sentence - MemFound.isDeclared = true - return deepCopy(MemFound) - } - return deepCopy(MemFound) - } - - function auxvarsGetMemoryObjectByLocation (loc: number|bigint|string, line: string = sentenceLine): MEMORY_SLOT { - let addr:number - switch (typeof loc) { - case 'number': addr = loc; break - case 'string': addr = parseInt(loc, 16); break - default: addr = Number(loc) - } - const FoundMemory = AuxVars.memory.find(obj => obj.address === addr) - 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: string, 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++ - return AuxVars.jumpId.toString(36) - } - - return setupGenCodeMain() -} diff --git a/src/codeGenerator/astProcessor/switchAsnProcessor.ts b/src/codeGenerator/astProcessor/switchAsnProcessor.ts index e0f96d7..56dd2ed 100644 --- a/src/codeGenerator/astProcessor/switchAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/switchAsnProcessor.ts @@ -1,12 +1,12 @@ import { CONTRACT } from '../../typings/contractTypes' import { SWITCH_ASN } from '../../typings/syntaxTypes' import { createInstruction, createSimpleInstruction } from '../assemblyProcessor/createInstruction' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import genCode from './genCode' export default function switchAsnProcessor ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ) : GENCODE_SOLVED_OBJECT { let CurrentNode: SWITCH_ASN @@ -14,7 +14,7 @@ export default function switchAsnProcessor ( CurrentNode = utils.assertAsnType('switchASN', ScopeInfo.RemAST) let assemblyCode = '' - const Expression = genCode(Program, AuxVars, { + const Expression = genCode(Program, { RemAST: CurrentNode.Expression, logicalOp: false, revLogic: ScopeInfo.revLogic @@ -28,14 +28,14 @@ export default function switchAsnProcessor ( return switchLogical(true) } CurrentNode.caseConditions.forEach((Cond, index) => { - const OneCondition = genCode(Program, AuxVars, { + const OneCondition = genCode(Program, { RemAST: Cond, logicalOp: false, revLogic: ScopeInfo.revLogic }) assemblyCode += OneCondition.asmCode assemblyCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), Expression.SolvedMem, OneCondition.SolvedMem, @@ -66,7 +66,7 @@ export default function switchAsnProcessor ( Args.jumpFalse = ScopeInfo.jumpFalse + '_' + index Args.jumpTrue = ScopeInfo.jumpFalse + '_' + index + '_next' } - const OneCondition = genCode(Program, AuxVars, Args) + const OneCondition = genCode(Program, Args) assemblyCode += OneCondition.asmCode assemblyCode += createSimpleInstruction('Label', ScopeInfo.jumpFalse + '_' + index + '_next') }) diff --git a/src/codeGenerator/astProcessor/unaryAsnProcessor.ts b/src/codeGenerator/astProcessor/unaryAsnProcessor.ts index e6a9f06..1fb600e 100644 --- a/src/codeGenerator/astProcessor/unaryAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/unaryAsnProcessor.ts @@ -1,14 +1,14 @@ import { deepCopy } from '../../repository/repository' -import { CONTRACT } from '../../typings/contractTypes' +import { CONTRACT, SC_FUNCTION } from '../../typings/contractTypes' import { MEMORY_SLOT, DECLARATION_TYPES, UNARY_ASN } from '../../typings/syntaxTypes' import { createSimpleInstruction, createInstruction } from '../assemblyProcessor/createInstruction' import { typeCasting } from '../assemblyProcessor/typeCastingToAsm' -import { GENCODE_AUXVARS, GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' +import { GENCODE_ARGS, GENCODE_SOLVED_OBJECT } from '../codeGeneratorTypes' import utils from '../utils' import genCode from './genCode' export default function unaryAsnProcessor ( - Program: CONTRACT, AuxVars: GENCODE_AUXVARS, ScopeInfo: GENCODE_ARGS + Program: CONTRACT, ScopeInfo: GENCODE_ARGS ): GENCODE_SOLVED_OBJECT { let CurrentNode: UNARY_ASN @@ -47,7 +47,7 @@ export default function unaryAsnProcessor ( function notOpProc () :GENCODE_SOLVED_OBJECT { if (ScopeInfo.logicalOp === true) { - return genCode(Program, AuxVars, { + return genCode(Program, { RemAST: CurrentNode.Center, logicalOp: true, revLogic: !ScopeInfo.revLogic, @@ -55,22 +55,22 @@ export default function unaryAsnProcessor ( jumpTrue: ScopeInfo.jumpFalse // Yes, this is swapped! }) } - const rnd = AuxVars.getNewJumpID() + const rnd = Program.Context.getNewJumpID() const idNotSF = '__NOT_' + rnd + '_sF' // set false const idNotST = '__NOT_' + rnd + '_sT' // set true const idEnd = '__NOT_' + rnd + '_end' - const CGenObj = genCode(Program, AuxVars, { + const CGenObj = genCode(Program, { RemAST: CurrentNode.Center, logicalOp: true, revLogic: !ScopeInfo.revLogic, jumpFalse: idNotST, jumpTrue: idNotSF }) - const TmpMemObj = AuxVars.getNewRegister() + const TmpMemObj = Program.Context.getNewRegister() // Logical return is long value! CGenObj.asmCode += createSimpleInstruction('Label', idNotST) CGenObj.asmCode += createInstruction( - AuxVars, + Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, utils.createConstantMemObj(1) @@ -78,18 +78,18 @@ export default function unaryAsnProcessor ( CGenObj.asmCode += createSimpleInstruction('Jump', idEnd) CGenObj.asmCode += createSimpleInstruction('Label', idNotSF) CGenObj.asmCode += createInstruction( - AuxVars, + Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, utils.createConstantMemObj(0) ) CGenObj.asmCode += createSimpleInstruction('Label', idEnd) - AuxVars.freeRegister(CGenObj.SolvedMem.address) + Program.Context.freeRegister(CGenObj.SolvedMem.address) return { SolvedMem: TmpMemObj, asmCode: CGenObj.asmCode } } function traverseDefault () : GENCODE_SOLVED_OBJECT { - return genCode(Program, AuxVars, { + return genCode(Program, { RemAST: CurrentNode.Center, logicalOp: ScopeInfo.logicalOp, revLogic: ScopeInfo.revLogic, @@ -99,7 +99,7 @@ export default function unaryAsnProcessor ( } function traverseNotLogical () : GENCODE_SOLVED_OBJECT { - return genCode(Program, AuxVars, { + return genCode(Program, { RemAST: CurrentNode.Center, logicalOp: false, revLogic: ScopeInfo.revLogic, @@ -110,7 +110,7 @@ export default function unaryAsnProcessor ( function pointerOpProc () : GENCODE_SOLVED_OBJECT { const CGenObj = traverseNotLogical() - if (AuxVars.isDeclaration.length !== 0) { + if (Program.Context.SentenceContext.isDeclaration.length !== 0) { // do not do any other operation when declaring a pointer. return CGenObj } @@ -126,13 +126,13 @@ export default function unaryAsnProcessor ( } if (CGenObj.SolvedMem.Offset) { // Double deference: deference and continue - const TmpMemObj = AuxVars.getNewRegister() + const TmpMemObj = Program.Context.getNewRegister() TmpMemObj.declaration = utils.getDeclarationFromMemory(CGenObj.SolvedMem) - CGenObj.asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, CGenObj.SolvedMem) + CGenObj.asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, CGenObj.SolvedMem) if (CGenObj.SolvedMem.Offset.type === 'variable') { - AuxVars.freeRegister(CGenObj.SolvedMem.Offset.addr) + Program.Context.freeRegister(CGenObj.SolvedMem.Offset.addr) } - AuxVars.freeRegister(CGenObj.SolvedMem.address) + Program.Context.freeRegister(CGenObj.SolvedMem.address) CGenObj.SolvedMem = TmpMemObj } CGenObj.SolvedMem.Offset = { @@ -142,7 +142,7 @@ export default function unaryAsnProcessor ( } if (ScopeInfo.logicalOp === true) { CGenObj.asmCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), CGenObj.SolvedMem, utils.createConstantMemObj(0), @@ -150,7 +150,7 @@ export default function unaryAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(CGenObj.SolvedMem.address) + Program.Context.freeRegister(CGenObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: CGenObj.asmCode } } return CGenObj @@ -167,14 +167,14 @@ export default function unaryAsnProcessor ( asmCode: asmCode } } - const TmpMemObj = AuxVars.getNewRegister() + const TmpMemObj = Program.Context.getNewRegister() TmpMemObj.declaration = utils.getDeclarationFromMemory(CGenObj) - asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, utils.createConstantMemObj(0)) - asmCode += createInstruction(AuxVars, utils.genSubToken(CurrentNode.Operation.line), TmpMemObj, CGenObj) - AuxVars.freeRegister(CGenObj.address) + asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, utils.createConstantMemObj(0)) + asmCode += createInstruction(Program, utils.genSubToken(CurrentNode.Operation.line), TmpMemObj, CGenObj) + Program.Context.freeRegister(CGenObj.address) if (ScopeInfo.logicalOp === true) { asmCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), TmpMemObj, utils.createConstantMemObj(0), @@ -182,7 +182,7 @@ export default function unaryAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(TmpMemObj.address) + Program.Context.freeRegister(TmpMemObj.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: asmCode } } return { SolvedMem: TmpMemObj, asmCode: asmCode } @@ -192,18 +192,18 @@ export default function unaryAsnProcessor ( let clearVar = false let { SolvedMem: CGenObj, asmCode } = traverseNotLogical() let TmpMemObj: MEMORY_SLOT - if (!AuxVars.isTemp(CGenObj.address)) { - TmpMemObj = AuxVars.getNewRegister() + if (!Program.Context.isTemp(CGenObj.address)) { + TmpMemObj = Program.Context.getNewRegister() TmpMemObj.declaration = utils.getDeclarationFromMemory(CGenObj) - asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, CGenObj) + asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, CGenObj) clearVar = true } else { TmpMemObj = CGenObj } - asmCode += createInstruction(AuxVars, CurrentNode.Operation, TmpMemObj) + asmCode += createInstruction(Program, CurrentNode.Operation, TmpMemObj) if (ScopeInfo.logicalOp === true) { asmCode += createInstruction( - AuxVars, + Program, utils.genNotEqualToken(), TmpMemObj, utils.createConstantMemObj(0), @@ -211,12 +211,12 @@ export default function unaryAsnProcessor ( ScopeInfo.jumpFalse, ScopeInfo.jumpTrue ) - AuxVars.freeRegister(CGenObj.address) - AuxVars.freeRegister(TmpMemObj.address) + Program.Context.freeRegister(CGenObj.address) + Program.Context.freeRegister(TmpMemObj.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: asmCode } } if (clearVar) { - AuxVars.freeRegister(CGenObj.address) + Program.Context.freeRegister(CGenObj.address) } return { SolvedMem: TmpMemObj, asmCode: asmCode } } @@ -250,14 +250,14 @@ export default function unaryAsnProcessor ( } const Copyvar = deepCopy(RetMem) delete Copyvar.Offset - TmpMemObj = AuxVars.getNewRegister() + TmpMemObj = Program.Context.getNewRegister() TmpMemObj.declaration = RetMem.declaration - asmCode += createInstruction(AuxVars, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, Copyvar) + asmCode += createInstruction(Program, utils.genAssignmentToken(CurrentNode.Operation.line), TmpMemObj, Copyvar) asmCode += createInstruction( - AuxVars, + Program, utils.genAddToken(), TmpMemObj, - AuxVars.getMemoryObjectByLocation(RetMem.Offset.addr) + Program.Context.getMemoryObjectByLocation(RetMem.Offset.addr) ) break } @@ -294,10 +294,10 @@ export default function unaryAsnProcessor ( case 'long': case 'fixed': case 'void': - AuxVars.isDeclaration = CurrentNode.Operation.value + Program.Context.SentenceContext.isDeclaration = CurrentNode.Operation.value return traverseNotLogical() case 'const': - AuxVars.isConstSentence = true + Program.Context.SentenceContext.isConstSentence = true return traverseNotLogical() case 'return': return returnKeyProc() @@ -308,7 +308,7 @@ export default function unaryAsnProcessor ( case 'sizeof': return sizeofKeyProc() case 'register': - AuxVars.isRegisterSentence = true + Program.Context.SentenceContext.isRegisterSentence = true return traverseNotLogical() case 'struct': // nothing to do here @@ -320,48 +320,49 @@ export default function unaryAsnProcessor ( } function returnKeyProc () : GENCODE_SOLVED_OBJECT { - if (AuxVars.CurrentFunction === undefined) { + const CurrentFunction: SC_FUNCTION | undefined = Program.functions[Program.Context.currFunctionIndex] + if (CurrentFunction === undefined) { throw new Error(`At line: ${CurrentNode.Operation.line}.` + " Can not use 'return' in global statements.") } - if (AuxVars.CurrentFunction.declaration === 'void') { + if (CurrentFunction.declaration === 'void') { throw new Error(`At line: ${CurrentNode.Operation.line}.` + - ` Function '${AuxVars.CurrentFunction.name}' must return` + - ` a ${AuxVars.CurrentFunction.declaration}' value.`) + ` Function '${CurrentFunction.name}' must return` + + ` a ${CurrentFunction.declaration}' value.`) } - if (AuxVars.CurrentFunction.name === 'main' || AuxVars.CurrentFunction.name === 'catch') { + if (CurrentFunction.name === 'main' || CurrentFunction.name === 'catch') { throw new Error(`At line: ${CurrentNode.Operation.line}. ` + - ` Special function ${AuxVars.CurrentFunction.name} must return void value.`) + ` Special function ${CurrentFunction.name} must return void value.`) } const CGenObj = traverseNotLogical() - CGenObj.asmCode += AuxVars.getPostOperations() - if (utils.isNotValidDeclarationOp(AuxVars.CurrentFunction.declaration, CGenObj.SolvedMem)) { + CGenObj.asmCode += Program.Context.SentenceContext.getAndClearPostOperations() + if (utils.isNotValidDeclarationOp(CurrentFunction.declaration, CGenObj.SolvedMem)) { throw new Error(`At line: ${CurrentNode.Operation.line}.` + - ` Function ${AuxVars.CurrentFunction.name} must return` + - ` '${AuxVars.CurrentFunction.declaration}' value,` + + ` Function ${CurrentFunction.name} must return` + + ` '${CurrentFunction.declaration}' value,` + ` but it is returning '${CGenObj.SolvedMem.declaration}'.`) } - CGenObj.asmCode += createInstruction(AuxVars, CurrentNode.Operation, CGenObj.SolvedMem) - AuxVars.freeRegister(CGenObj.SolvedMem.address) + CGenObj.asmCode += createInstruction(Program, CurrentNode.Operation, CGenObj.SolvedMem) + Program.Context.freeRegister(CGenObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: CGenObj.asmCode } } function gotoKeyProc () : GENCODE_SOLVED_OBJECT { const CGenObj = traverseNotLogical() - CGenObj.asmCode += AuxVars.getPostOperations() + CGenObj.asmCode += Program.Context.SentenceContext.getAndClearPostOperations() if (CGenObj.SolvedMem.type !== 'label') { throw new Error(`At line: ${CurrentNode.Operation.line}. Argument for keyword 'goto' is not a label.`) } - CGenObj.asmCode += createInstruction(AuxVars, CurrentNode.Operation, CGenObj.SolvedMem) - AuxVars.freeRegister(CGenObj.SolvedMem.address) + CGenObj.asmCode += createInstruction(Program, CurrentNode.Operation, CGenObj.SolvedMem) + Program.Context.freeRegister(CGenObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: CGenObj.asmCode } } function sleepKeyProc () : GENCODE_SOLVED_OBJECT { const CGenObj = traverseNotLogical() - CGenObj.asmCode += AuxVars.getPostOperations() - CGenObj.asmCode += createInstruction(AuxVars, CurrentNode.Operation, CGenObj.SolvedMem) - AuxVars.freeRegister(CGenObj.SolvedMem.address) + CGenObj.asmCode += Program.Context.SentenceContext.getAndClearPostOperations() + CGenObj.asmCode += createInstruction(Program, CurrentNode.Operation, CGenObj.SolvedMem) + Program.Context.freeRegister(CGenObj.SolvedMem.address) return { SolvedMem: utils.createVoidMemObj(), asmCode: CGenObj.asmCode } } @@ -386,7 +387,7 @@ export default function unaryAsnProcessor ( if (cDecl === CurrentNode.Operation.declaration) { return CGenObj } - return typeCasting(AuxVars, CGenObj, CurrentNode.Operation.declaration, CurrentNode.Operation.line) + return typeCasting(Program, CGenObj, CurrentNode.Operation.declaration, CurrentNode.Operation.line) } return unaryAsnProcessorMain() diff --git a/src/codeGenerator/codeGenerator.ts b/src/codeGenerator/codeGenerator.ts index 21acdfc..8c02e85 100644 --- a/src/codeGenerator/codeGenerator.ts +++ b/src/codeGenerator/codeGenerator.ts @@ -1,10 +1,15 @@ -import { assertNotUndefined } from '../repository/repository' +import { assertNotUndefined, deepCopy } from '../repository/repository' import { CONTRACT } from '../typings/contractTypes' -import { MEMORY_SLOT, SENTENCES } from '../typings/syntaxTypes' +import { AST, DECLARATION_TYPES, MEMORY_SLOT, SENTENCES } from '../typings/syntaxTypes' import optimizer from './assemblyProcessor/optimizer' -import setupGenCode from './astProcessor/setupGenCode' +import genCode from './astProcessor/genCode' -import { GLOBAL_AUXVARS } from './codeGeneratorTypes' +type SETUPGENCODE_ARGS = { + InitialAST?: AST + initialJumpTarget?: string + initialJumpNotTarget?:string + initialIsReversedLogic?: boolean +} /** * Code generator. Translates a Program into assembly source code @@ -13,8 +18,11 @@ import { GLOBAL_AUXVARS } from './codeGeneratorTypes' */ export default function codeGenerator (Program: CONTRACT) { // holds variables needed during compilation - const GlobalCodeVars: GLOBAL_AUXVARS = { - Program: Program, + Program.Context = { + registerInfo: [], + isTemp, + getNewRegister, + freeRegister, latestLoopId: [], jumpId: 0, assemblyCode: '', @@ -47,7 +55,7 @@ export default function codeGenerator (Program: CONTRACT) { registers += `,r${i}` } } - GlobalCodeVars.assemblyCode += `^comment scope ${registers}\n` + this.assemblyCode += `^comment scope ${registers}\n` }, startScope: function (scopeName: string) { this.scopedRegisters.push(scopeName) @@ -66,11 +74,29 @@ export default function codeGenerator (Program: CONTRACT) { ), 'Internal error') motherMemory.address = -1 motherMemory.asmName = '' + const Reg = assertNotUndefined(this.registerInfo.find(Item => Item.Template.asmName === liberationNeeded)) + Reg.inUse = false + Reg.endurance = 'Standard' } } while (liberationNeeded !== scopeName) if (Program.Config.verboseScope) { this.printFreeRegisters() } + }, + getMemoryObjectByName, + getMemoryObjectByLocation, + SentenceContext: { + isDeclaration: '', + isLeftSideOfAssignment: false, + isConstSentence: false, + isRegisterSentence: false, + hasVoidArray: false, + postOperations: '', + getAndClearPostOperations: function () { + const ret = this.postOperations + this.postOperations = '' + return ret + } } } @@ -85,11 +111,20 @@ export default function codeGenerator (Program: CONTRACT) { if (Program.functions.findIndex(obj => obj.name === 'catch') !== -1) { writeAsmLine('ERR :__fn_catch') } + // Set up registers info + Program.memory.filter(OBJ => /^r\d$/.test(OBJ.asmName) && OBJ.type === 'register').forEach(MEM => { + Program.Context.registerInfo.push({ + endurance: 'Standard', + inUse: false, + Template: MEM + }) + }) + // Add code for global sentences - GlobalCodeVars.currFunctionIndex = -1 - GlobalCodeVars.startScope('global') + Program.Context.currFunctionIndex = -1 + Program.Context.startScope('global') Program.Global.sentences.forEach(compileSentence) - GlobalCodeVars.stopScope('global') + Program.Context.stopScope('global') // jump to main function, or program ends. if (Program.functions.find(obj => obj.name === 'main') === undefined) { writeAsmLine('FIN') @@ -105,21 +140,21 @@ export default function codeGenerator (Program: CONTRACT) { } return } - GlobalCodeVars.currFunctionIndex = index + Program.Context.currFunctionIndex = index writeAsmLine('') // blank line to be nice to debugger! functionHeaderGenerator() // add code for functions sentences. if (currentFunction.sentences !== undefined) { - GlobalCodeVars.startScope(currentFunction.name) + Program.Context.startScope(currentFunction.name) currentFunction.sentences.forEach(compileSentence) - GlobalCodeVars.stopScope(currentFunction.name) + Program.Context.stopScope(currentFunction.name) } functionTailGenerator() }) let calls = 0 - while (/^%inline\.(\w+)%$/m.test(GlobalCodeVars.assemblyCode)) { + while (/^%inline\.(\w+)%$/m.test(Program.Context.assemblyCode)) { calls++ - GlobalCodeVars.assemblyCode = GlobalCodeVars.assemblyCode.replace(/^%inline\.(\w+)%$/m, substituteInlineFunction) + Program.Context.assemblyCode = Program.Context.assemblyCode.replace(/^%inline\.(\w+)%$/m, substituteInlineFunction) if (calls > 200) { throw new Error('At line: unknow. Maximum number of inline substitutions. ' + 'Inline cannot be used in recursive functions neither have circular dependency of each other.') @@ -127,29 +162,29 @@ export default function codeGenerator (Program: CONTRACT) { } checkUnusedVariables() // Inspect if there were errros and throw now - if (GlobalCodeVars.errors.length !== 0) { - throw new Error(GlobalCodeVars.errors + Program.warnings) + if (Program.Context.errors.length !== 0) { + throw new Error(Program.Context.errors + Program.warnings) } return optimizer( Program.Config.optimizationLevel, - GlobalCodeVars.assemblyCode, + Program.Context.assemblyCode, Program.memory.filter(Obj => Obj.type === 'label').map(Res => Res.asmName) ) } function substituteInlineFunction (match: string, g1: string) { - GlobalCodeVars.currFunctionIndex = Program.functions.findIndex(fn => fn.name === g1) - const func = Program.functions[GlobalCodeVars.currFunctionIndex] - const inlineId = GlobalCodeVars.getNewJumpID() - const EndOfPreviousCode = GlobalCodeVars.assemblyCode.length + Program.Context.currFunctionIndex = Program.functions.findIndex(fn => fn.name === g1) + const func = Program.functions[Program.Context.currFunctionIndex] + const inlineId = Program.Context.getNewJumpID() + const EndOfPreviousCode = Program.Context.assemblyCode.length // add code for functions sentences. if (func.sentences !== undefined) { - GlobalCodeVars.startScope(`inline_${inlineId}`) + Program.Context.startScope(`inline_${inlineId}`) func.sentences.forEach(compileSentence) - GlobalCodeVars.stopScope(`inline_${inlineId}`) + Program.Context.stopScope(`inline_${inlineId}`) } // Function code is in the end of assembly code, it will be substituded in the middle. - const functionCode = GlobalCodeVars.assemblyCode.slice(EndOfPreviousCode) + const functionCode = Program.Context.assemblyCode.slice(EndOfPreviousCode) return `__inline${inlineId}_start:\n` + functionCode.replace(/RET/g, `JMP :__inline${inlineId}_end`) + `__inline${inlineId}_end:` @@ -160,11 +195,11 @@ export default function codeGenerator (Program: CONTRACT) { const lineNumber = Number(location[0]) if (Program.Config.verboseAssembly === true && sourceCodeLine !== '0:0' && - lineNumber !== GlobalCodeVars.currSourceLine) { - GlobalCodeVars.assemblyCode += `^comment line ${location[0]} ${Program.sourceLines[lineNumber - 1]}\n` - GlobalCodeVars.currSourceLine = lineNumber + lineNumber !== Program.Context.currSourceLine) { + Program.Context.assemblyCode += `^comment line ${location[0]} ${Program.sourceLines[lineNumber - 1]}\n` + Program.Context.currSourceLine = lineNumber } - GlobalCodeVars.assemblyCode += lineContent + '\n' + Program.Context.assemblyCode += lineContent + '\n' } function writeAsmCode (lines: string, sourceCodeLine: string = '0:0') { @@ -175,15 +210,15 @@ export default function codeGenerator (Program: CONTRACT) { const lineNumber = Number(location[0]) if (Program.Config.verboseAssembly === true && lineNumber !== 0 && - lineNumber !== GlobalCodeVars.currSourceLine) { - GlobalCodeVars.assemblyCode += `^comment line ${location[0]} ${Program.sourceLines[lineNumber - 1]}\n` - GlobalCodeVars.currSourceLine = lineNumber + lineNumber !== Program.Context.currSourceLine) { + Program.Context.assemblyCode += `^comment line ${location[0]} ${Program.sourceLines[lineNumber - 1]}\n` + Program.Context.currSourceLine = lineNumber } - GlobalCodeVars.assemblyCode += lines + Program.Context.assemblyCode += lines } function addError (erroMessage: string) { - GlobalCodeVars.errors += erroMessage + '\n' + Program.Context.errors += erroMessage + '\n' } /** Add content of macro 'program' information to assembly code */ @@ -228,27 +263,27 @@ export default function codeGenerator (Program: CONTRACT) { * Handle function initialization */ function functionHeaderGenerator () { - const fname = Program.functions[GlobalCodeVars.currFunctionIndex].name + const fname = Program.functions[Program.Context.currFunctionIndex].name if (fname === 'main' || fname === 'catch') { - writeAsmLine(`__fn_${fname}:`, Program.functions[GlobalCodeVars.currFunctionIndex].line) + writeAsmLine(`__fn_${fname}:`, Program.functions[Program.Context.currFunctionIndex].line) writeAsmLine('PCS') return } - writeAsmLine(`__fn_${fname}:`, Program.functions[GlobalCodeVars.currFunctionIndex].line) + writeAsmLine(`__fn_${fname}:`, Program.functions[Program.Context.currFunctionIndex].line) } /** * Handle function end */ function functionTailGenerator () { - const fname = Program.functions[GlobalCodeVars.currFunctionIndex].name + const fname = Program.functions[Program.Context.currFunctionIndex].name if (fname === 'main' || fname === 'catch') { - if (GlobalCodeVars.assemblyCode.lastIndexOf('FIN') + 4 !== GlobalCodeVars.assemblyCode.length) { + if (Program.Context.assemblyCode.lastIndexOf('FIN') + 4 !== Program.Context.assemblyCode.length) { writeAsmLine('FIN') } return } - if (GlobalCodeVars.assemblyCode.lastIndexOf('RET') + 4 !== GlobalCodeVars.assemblyCode.length) { + if (Program.Context.assemblyCode.lastIndexOf('RET') + 4 !== Program.Context.assemblyCode.length) { writeAsmLine('RET') } } @@ -273,7 +308,7 @@ export default function codeGenerator (Program: CONTRACT) { case 'phrase': try { writeAsmCode( - setupGenCode(GlobalCodeVars, { InitialAST: Sentence.CodeAST }, Sentence.line), + setupGenCode({ InitialAST: Sentence.CodeAST }), Sentence.line ) } catch (err) { @@ -286,124 +321,124 @@ export default function codeGenerator (Program: CONTRACT) { } break case 'ifEndif': - sentenceID = '__if' + GlobalCodeVars.getNewJumpID() - assemblyCode = setupGenCode(GlobalCodeVars, { + sentenceID = '__if' + Program.Context.getNewJumpID() + assemblyCode = setupGenCode({ InitialAST: Sentence.ConditionAST, initialJumpTarget: sentenceID + '_endif', initialJumpNotTarget: sentenceID + '_start' - }, Sentence.line) + }) writeAsmCode(assemblyCode, Sentence.line) writeAsmLine(sentenceID + '_start:') - GlobalCodeVars.startScope(`scope_${sentenceID}`) + Program.Context.startScope(`scope_${sentenceID}`) Sentence.trueBlock.forEach(compileSentence) writeAsmLine(sentenceID + '_endif:') - GlobalCodeVars.stopScope(`scope_${sentenceID}`) + Program.Context.stopScope(`scope_${sentenceID}`) break case 'ifElse': - sentenceID = '__if' + GlobalCodeVars.getNewJumpID() - assemblyCode = setupGenCode(GlobalCodeVars, { + sentenceID = '__if' + Program.Context.getNewJumpID() + assemblyCode = setupGenCode({ InitialAST: Sentence.ConditionAST, initialJumpTarget: sentenceID + '_else', initialJumpNotTarget: sentenceID + '_start' - }, Sentence.line) + }) writeAsmCode(assemblyCode, Sentence.line) writeAsmLine(sentenceID + '_start:') - GlobalCodeVars.startScope(`scope_${sentenceID}`) + Program.Context.startScope(`scope_${sentenceID}`) Sentence.trueBlock.forEach(compileSentence) - GlobalCodeVars.stopScope(`scope_${sentenceID}`) + Program.Context.stopScope(`scope_${sentenceID}`) writeAsmLine('JMP :' + sentenceID + '_endif') writeAsmLine(sentenceID + '_else:') - GlobalCodeVars.startScope(`scope2_${sentenceID}`) + Program.Context.startScope(`scope2_${sentenceID}`) Sentence.falseBlock.forEach(compileSentence) writeAsmLine(sentenceID + '_endif:') - GlobalCodeVars.stopScope(`scope2_${sentenceID}`) + Program.Context.stopScope(`scope2_${sentenceID}`) break case 'while': - sentenceID = '__loop' + GlobalCodeVars.getNewJumpID() - GlobalCodeVars.startScope(`scope_${sentenceID}`) + sentenceID = '__loop' + Program.Context.getNewJumpID() + Program.Context.startScope(`scope_${sentenceID}`) writeAsmLine(sentenceID + '_continue:', Sentence.line) - assemblyCode = setupGenCode(GlobalCodeVars, { + assemblyCode = setupGenCode({ InitialAST: Sentence.ConditionAST, initialJumpTarget: sentenceID + '_break', initialJumpNotTarget: sentenceID + '_start' - }, Sentence.line) + }) writeAsmCode(assemblyCode) writeAsmLine(sentenceID + '_start:') - GlobalCodeVars.latestLoopId.push(sentenceID) + Program.Context.latestLoopId.push(sentenceID) Sentence.trueBlock.forEach(compileSentence) - GlobalCodeVars.latestLoopId.pop() + Program.Context.latestLoopId.pop() writeAsmLine('JMP :' + sentenceID + '_continue') writeAsmLine(sentenceID + '_break:') - GlobalCodeVars.stopScope(`scope_${sentenceID}`) + Program.Context.stopScope(`scope_${sentenceID}`) break case 'do': - sentenceID = '__loop' + GlobalCodeVars.getNewJumpID() - GlobalCodeVars.startScope(`scope2_${sentenceID}`) + sentenceID = '__loop' + Program.Context.getNewJumpID() + Program.Context.startScope(`scope2_${sentenceID}`) writeAsmLine(sentenceID + '_continue:', Sentence.line) - GlobalCodeVars.latestLoopId.push(sentenceID) + Program.Context.latestLoopId.push(sentenceID) Sentence.trueBlock.forEach(compileSentence) - GlobalCodeVars.latestLoopId.pop() - assemblyCode = setupGenCode(GlobalCodeVars, { + Program.Context.latestLoopId.pop() + assemblyCode = setupGenCode({ InitialAST: Sentence.ConditionAST, initialJumpTarget: sentenceID + '_break', initialJumpNotTarget: sentenceID + '_continue', initialIsReversedLogic: true - }, Sentence.line) + }) writeAsmCode(assemblyCode) writeAsmLine(sentenceID + '_break:') - GlobalCodeVars.stopScope(`scope2_${sentenceID}`) + Program.Context.stopScope(`scope2_${sentenceID}`) break case 'for': - sentenceID = '__loop' + GlobalCodeVars.getNewJumpID() - GlobalCodeVars.startScope(`scope_${sentenceID}`) - assemblyCode = setupGenCode(GlobalCodeVars, { + sentenceID = '__loop' + Program.Context.getNewJumpID() + Program.Context.startScope(`scope_${sentenceID}`) + assemblyCode = setupGenCode({ InitialAST: Sentence.threeSentences[0].CodeAST - }, Sentence.line) + }) writeAsmCode(assemblyCode, Sentence.line) writeAsmLine(sentenceID + '_condition:') - assemblyCode = setupGenCode(GlobalCodeVars, { + assemblyCode = setupGenCode({ InitialAST: Sentence.threeSentences[1].CodeAST, initialJumpTarget: sentenceID + '_break', initialJumpNotTarget: sentenceID + '_start' - }, Sentence.line) + }) writeAsmCode(assemblyCode, Sentence.line) writeAsmLine(sentenceID + '_start:') - GlobalCodeVars.latestLoopId.push(sentenceID) + Program.Context.latestLoopId.push(sentenceID) Sentence.trueBlock.forEach(compileSentence) - GlobalCodeVars.latestLoopId.pop() + Program.Context.latestLoopId.pop() writeAsmLine(sentenceID + '_continue:') - assemblyCode = setupGenCode(GlobalCodeVars, { + assemblyCode = setupGenCode({ InitialAST: Sentence.threeSentences[2].CodeAST - }, Sentence.line) + }) writeAsmCode(assemblyCode, Sentence.line) writeAsmLine('JMP :' + sentenceID + '_condition') writeAsmLine(sentenceID + '_break:') - GlobalCodeVars.stopScope(`scope_${sentenceID}`) + Program.Context.stopScope(`scope_${sentenceID}`) break case 'switch': { - sentenceID = '__switch' + GlobalCodeVars.getNewJumpID() - GlobalCodeVars.startScope(`scope_${sentenceID}`) + sentenceID = '__switch' + Program.Context.getNewJumpID() + Program.Context.startScope(`scope_${sentenceID}`) let jumpTgt = sentenceID jumpTgt += Sentence.hasDefault ? '_default' : '_break' - assemblyCode = setupGenCode(GlobalCodeVars, { + assemblyCode = setupGenCode({ InitialAST: Sentence.JumpTable, initialJumpTarget: sentenceID, initialJumpNotTarget: jumpTgt, initialIsReversedLogic: false - }, Sentence.line) + }) writeAsmCode(assemblyCode, Sentence.line) - GlobalCodeVars.latestLoopId.push(sentenceID) + Program.Context.latestLoopId.push(sentenceID) Sentence.block.forEach(compileSentence) - GlobalCodeVars.latestLoopId.pop() + Program.Context.latestLoopId.pop() writeAsmLine(sentenceID + '_break:') - GlobalCodeVars.stopScope(`scope_${sentenceID}`) + Program.Context.stopScope(`scope_${sentenceID}`) break } case 'case': - writeAsmLine(GlobalCodeVars.getLatestLoopID() + Sentence.caseId + ':', Sentence.line) + writeAsmLine(Program.Context.getLatestLoopID() + Sentence.caseId + ':', Sentence.line) break case 'default': - writeAsmLine(GlobalCodeVars.getLatestLoopID() + '_default:', Sentence.line) + writeAsmLine(Program.Context.getLatestLoopID() + '_default:', Sentence.line) break case 'label': writeAsmLine(Sentence.id + ':', Sentence.line) @@ -413,5 +448,139 @@ export default function codeGenerator (Program: CONTRACT) { } } + function getMemoryObjectByName ( + varName: string, line: string, varDeclaration: DECLARATION_TYPES = '' + ) : MEMORY_SLOT { + let MemFound: MEMORY_SLOT | undefined + if (Program.Context.currFunctionIndex >= 0) { // find function scope variable + MemFound = Program.memory.find(obj => { + return obj.name === varName && obj.scope === Program.functions[Program.Context.currFunctionIndex].name + }) + } + if (MemFound === undefined) { + // do a global scope search + MemFound = Program.memory.find(obj => obj.name === varName && obj.scope === '') + } + if (MemFound === undefined) { + throw new Error(`At line: ${line}. Using variable '${varName}' before declaration.`) + } + if (MemFound.toBeRegister && MemFound.asmName === '') { + throw new Error(`At line: ${line}. Using variable '${varName}' out of scope!`) + } + if (!MemFound.isSet) { + detectAndSetNotInitialized(MemFound, line, varDeclaration !== '') + } + if (varDeclaration !== '') { // we are in declarations sentence + MemFound.isDeclared = true + return deepCopy(MemFound) + } + return deepCopy(MemFound) + } + + function getMemoryObjectByLocation (loc: number|bigint|string, line: string): MEMORY_SLOT { + let addr:number + switch (typeof loc) { + case 'number': addr = loc; break + case 'string': addr = parseInt(loc, 16); break + default: addr = Number(loc) + } + const FoundMemory = Program.memory.find(obj => obj.address === addr) + 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: string, isInitialization: boolean) { + if (Program.Context.SentenceContext.isLeftSideOfAssignment || Memory.hexContent) { + Memory.isSet = true + return + } + if (isInitialization) { + return + } + Program.warnings.push(`Warning: at line ${line}. Variable '${Memory.name}' is used but not initialized.`) + Memory.isSet = true // No more warning for same variable + } + + function isTemp (loc: number) : boolean { + if (loc === -1) return false + const id = Program.Context.registerInfo.find(OBJ => OBJ.Template.address === loc) + if (id === undefined) { + return false + } + if (Program.Context.scopedRegisters.find(items => items === id.Template.asmName)) { + // It is a register, but scoped. Do not mess!!! + return false + } + return true + } + + function getNewRegister (line: string): MEMORY_SLOT { + const id = Program.Context.registerInfo.find(OBJ => OBJ.inUse === false) + if (id === undefined) { + throw new Error(`At line: ${line}. ` + + 'No more registers available. ' + + `Increase the number with '#pragma maxAuxVars ${Program.Config.maxAuxVars + 1}' or try to reduce nested operations.`) + } + id.inUse = true + return deepCopy(id.Template) + } + + function freeRegister (loc: number|undefined): void { + if (loc === undefined || loc === -1) { + return + } + const RegInfo = Program.Context.registerInfo.find(OBJ => OBJ.Template.address === loc) + if (RegInfo === undefined) return + if (RegInfo.endurance === 'Scope') return + RegInfo.inUse = false + } + + /** Run to start compilation in each sentence. */ + function setupGenCode (CodeGenInfo: SETUPGENCODE_ARGS): string { + CodeGenInfo.InitialAST = assertNotUndefined(CodeGenInfo.InitialAST) + CodeGenInfo.initialIsReversedLogic = CodeGenInfo.initialIsReversedLogic ?? false + Program.Context.SentenceContext.isDeclaration = '' + Program.Context.SentenceContext.isLeftSideOfAssignment = false + Program.Context.SentenceContext.isConstSentence = false + Program.Context.SentenceContext.isRegisterSentence = false + Program.Context.SentenceContext.hasVoidArray = false + Program.Context.SentenceContext.postOperations = '' + + const code = genCode(Program, { + RemAST: CodeGenInfo.InitialAST, + logicalOp: CodeGenInfo.initialJumpTarget !== undefined, + revLogic: CodeGenInfo.initialIsReversedLogic, + jumpFalse: CodeGenInfo.initialJumpTarget, + jumpTrue: CodeGenInfo.initialJumpNotTarget + }) + + validateReturnedVariable(CodeGenInfo.InitialAST, code.SolvedMem, CodeGenInfo.initialJumpTarget) + code.asmCode += Program.Context.SentenceContext.postOperations + if (code.SolvedMem.Offset?.type === 'variable') { + Program.Context.freeRegister(code.SolvedMem.Offset.addr) + } + Program.Context.freeRegister(code.SolvedMem.address) + Program.Context.registerInfo = Program.Context.registerInfo.filter(Item => Item.endurance !== 'Sentence') + + return code.asmCode + } + + function validateReturnedVariable (InitAST: AST, RetObj: MEMORY_SLOT, initialJumpTarget: string | undefined) { + if (initialJumpTarget === undefined && + RetObj.type === 'register') { + if ((InitAST.type === 'unaryASN' && InitAST.Operation.value !== '*') || + (InitAST.type === 'binaryASN' && + (InitAST.Operation.type === 'Comparision' || InitAST.Operation.type === 'Operator'))) { + throw new Error(`At line: ${InitAST.Operation.line}. ` + + 'Operation returning a value that is not being used. Use casting to (void) to avoid this error.') + } + } + } + return generateMain() } diff --git a/src/codeGenerator/codeGeneratorTypes.ts b/src/codeGenerator/codeGeneratorTypes.ts index b1ba7c6..dc5f26b 100644 --- a/src/codeGenerator/codeGeneratorTypes.ts +++ b/src/codeGenerator/codeGeneratorTypes.ts @@ -1,9 +1,22 @@ -import { CONTRACT, SC_FUNCTION } from '../typings/contractTypes' import { AST, DECLARATION_TYPES, MEMORY_SLOT } from '../typings/syntaxTypes' -export type GLOBAL_AUXVARS = { - /** Holds incoming program. To be read-only */ - Program: CONTRACT +export type SENTENCE_CONTEXT = { + /** Flag to inform lower level AST that it is declaration sentence */ + isDeclaration: DECLARATION_TYPES + /** Flag to inform lower level AST that it is left side of assignment */ + isLeftSideOfAssignment: boolean + /** Flag to inform lower level AST that it is const declaration sentence */ + isConstSentence: boolean + /** Flag to inform lower level AST that it is register declaration sentence */ + isRegisterSentence: boolean + /** Flag to inform lower level AST that there are an void array assignment */ + hasVoidArray: boolean + getAndClearPostOperations(): string + /** Post increment or decrement that shall be included at last */ + postOperations: string +} + +export type GLOBAL_CONTEXT = { /** Stack saving loops IDs */ latestLoopId: string[] /** Auto incrementing index for labels generation */ @@ -30,63 +43,18 @@ export type GLOBAL_AUXVARS = { startScope(arg :string): void /** Operations to close a scope for registers */ stopScope(arg :string): void -} - -export type SETUPGENCODE_ARGS = { - InitialAST?: AST - initialJumpTarget?: string - initialJumpNotTarget?:string - initialIsReversedLogic?: boolean -} - -export type GENCODE_ARGS = { - /** AST to traverse */ - RemAST: AST, - /** true if wanted return object to be suitable for logical operations */ - logicalOp: boolean, - /** true if wanted to reverse logic for logical operations */ - revLogic: boolean, - /** Label to jump if logical operation is false */ - jumpFalse?: string, - /** Label to jump if logical operatio is true */ - jumpTrue?: string -} - -export type GENCODE_AUXVARS = { - /** Current function, or undefined if Global code */ - CurrentFunction: SC_FUNCTION | undefined - /** Program memory that will be used and (and property isDeclared can be modified) by codeGenerator */ - memory: MEMORY_SLOT[] /** Auxiliary variables used as registers */ registerInfo: { + endurance: 'Standard' | 'Sentence' | 'Scope' inUse: boolean Template: MEMORY_SLOT }[] - /** Auto incrementing index for labels generation in genCode scope */ - jumpId: number - /** Post increment or decrement that shall be included at last */ - postOperations: string - /** Flag to inform lower level AST that it is declaration sentence */ - isDeclaration: DECLARATION_TYPES - /** Flag to inform lower level AST that it is left side of assignment */ - isLeftSideOfAssignment: boolean - /** Flag to inform lower level AST that it is const declaration sentence */ - isConstSentence: boolean - /** Flag to inform lower level AST that it is register declaration sentence */ - isRegisterSentence: boolean - /** Flag to inform lower level AST that there are an void array assignment */ - hasVoidArray: boolean - /** Warnings found */ - warnings: string[] - scopedRegisters: string[] /** Verifies if a variable at loc address is register or temporary reused var */ isTemp(loc: number): boolean /** Get a new register variable */ getNewRegister(line?: string): MEMORY_SLOT /** Informs that variable at loc address can be free */ freeRegister(loc: number | undefined): void - /** Get all post operations and clear its value */ - getPostOperations(): string /** * Search and return a copy of memory object with name varname. * Object can be global or local function scope. @@ -100,8 +68,21 @@ export type GENCODE_AUXVARS = { * if not found, throws exception with line number. */ getMemoryObjectByLocation (loc: number|bigint|string, line?: string): MEMORY_SLOT - /** Get a new jump id according to current Configs (genCode scope) */ - getNewJumpID(): string + /** Options to be used in each sentence */ + SentenceContext: SENTENCE_CONTEXT +} + +export type GENCODE_ARGS = { + /** AST to traverse */ + RemAST: AST, + /** true if wanted return object to be suitable for logical operations */ + logicalOp: boolean, + /** true if wanted to reverse logic for logical operations */ + revLogic: boolean, + /** Label to jump if logical operation is false */ + jumpFalse?: string, + /** Label to jump if logical operatio is true */ + jumpTrue?: string } export type GENCODE_SOLVED_OBJECT = { diff --git a/src/typings/contractTypes.ts b/src/typings/contractTypes.ts index 799f8ce..42ee510 100644 --- a/src/typings/contractTypes.ts +++ b/src/typings/contractTypes.ts @@ -1,3 +1,4 @@ +import { GLOBAL_CONTEXT } from '../codeGenerator/codeGeneratorTypes' import { BUILTIN_TYPES, DECLARATION_TYPES, MEMORY_SLOT, SENTENCES, TOKEN, TYPE_DEFINITIONS } from './syntaxTypes' export type SC_CONFIG = { @@ -99,6 +100,8 @@ export type CONTRACT = { typesDefinitions: TYPE_DEFINITIONS[], /** Compiler configurations */ Config: SC_CONFIG, + /** Variables and helper functions */ + Context: GLOBAL_CONTEXT /** Compilation warnings */ warnings: string[], } From ad3e83ef858f83785cd17a50a6fda6a92e6252cb Mon Sep 17 00:00:00 2001 From: deleterium Date: Mon, 19 Feb 2024 21:17:13 -0300 Subject: [PATCH 2/5] Solving mess at reusing left side of assignment. --- .../astProcessor/binaryAsnProcessor.ts | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts index 88c5bce..b8f6eb6 100644 --- a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts @@ -283,31 +283,22 @@ export default function binaryAsnProcessor ( jumpFalse: ScopeInfo.jumpFalse, jumpTrue: ScopeInfo.jumpTrue }) - const registerFinalState = deepCopy(AuxVars.registerInfo) - // if returning var is not the reused one, put it in that returning location and solve right side again - if (RetGenObj.SolvedMem.address !== Left.address && AuxVars.isTemp(RetGenObj.SolvedMem.address)) { - AuxVars.registerInfo.shift() - const index = RetGenObj.SolvedMem.address + 1 - AuxVars.registerInfo = registerInitialState - AuxVars.registerInfo.splice(index, 0, { inUse: false, Template: NewRegister }) - const TestRetGenObj = genCode(Program, AuxVars, { - RemAST: CurrentNode.Right, - logicalOp: false, - revLogic: ScopeInfo.revLogic, - jumpFalse: ScopeInfo.jumpFalse, - jumpTrue: ScopeInfo.jumpTrue - }) - // Verify if alteration suceed in optimization - if (TestRetGenObj.SolvedMem.address === Left.address) { - // alteration suceed! - // RetGenObj = TestRGenObj - AuxVars.registerInfo.splice(index, 1) - return TestRetGenObj - } - // not suceed, undo changes. - AuxVars.registerInfo = registerFinalState - } - return RetGenObj + if (RetGenObj.SolvedMem.address === Left.address || !Program.Context.isTemp(RetGenObj.SolvedMem.address)) { + // Strategy to reuse was right on first try! + return RetGenObj + } + // If returning var is not the reused one, put it in that returning location and solve right side again + const index = RetGenObj.SolvedMem.address + 1 + Program.Context.registerInfo = registerInitialState + Program.Context.registerInfo.splice(index, 0, { endurance: 'Sentence', inUse: false, Template: NewRegister }) + const TestRetGenObj = genCode(Program, { + RemAST: CurrentNode.Right, + logicalOp: false, + revLogic: ScopeInfo.revLogic, + jumpFalse: ScopeInfo.jumpFalse, + jumpTrue: ScopeInfo.jumpTrue + }) + return TestRetGenObj } /** Tests if implicit type casting is needed and also checks valid operations for binary operators. From bf25abe2373f60ec25c3233caf27092fccfbe22e Mon Sep 17 00:00:00 2001 From: deleterium Date: Mon, 19 Feb 2024 21:18:45 -0300 Subject: [PATCH 3/5] Fix: operation not releasing register after use. --- src/codeGenerator/assemblyProcessor/assignmentToAsm.ts | 1 + src/codeGenerator/assemblyProcessor/createInstruction.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts b/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts index e78496c..00b5dc9 100644 --- a/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts +++ b/src/codeGenerator/assemblyProcessor/assignmentToAsm.ts @@ -149,6 +149,7 @@ export default function assignmentToAsm ( } // Right.Offset.type is 'variable' const offsetVarName = Program.Context.getMemoryObjectByLocation(Right.Offset.addr, operationLine).asmName + Program.Context.freeRegister(Right.Offset.addr) return `SET @${Left.asmName} $($${Right.asmName} + $${offsetVarName})\n` } diff --git a/src/codeGenerator/assemblyProcessor/createInstruction.ts b/src/codeGenerator/assemblyProcessor/createInstruction.ts index 9523d31..47b0bab 100644 --- a/src/codeGenerator/assemblyProcessor/createInstruction.ts +++ b/src/codeGenerator/assemblyProcessor/createInstruction.ts @@ -147,6 +147,7 @@ export function flattenMemory ( RetObj.declaration = paramDec const offsetVarName = Program.Context.getMemoryObjectByLocation(StuffedMemory.Offset.addr, line).asmName retInstructions += `SET @${RetObj.asmName} $($${StuffedMemory.asmName} + $${offsetVarName})\n` + Program.Context.freeRegister(StuffedMemory.Offset.addr) return { FlatMem: RetObj, asmCode: retInstructions, isNew: true } } // StuffedMemory.Offset.type is 'constant' From 0540a05d2de7aba680ffe7d2739a1fe1ec7fc9fb Mon Sep 17 00:00:00 2001 From: deleterium Date: Mon, 19 Feb 2024 23:23:45 -0300 Subject: [PATCH 4/5] refactor: Moving warning inside Context --- src/codeGenerator/astProcessor/binaryAsnProcessor.ts | 10 +++++----- src/codeGenerator/codeGenerator.ts | 6 +++--- src/codeGenerator/codeGeneratorTypes.ts | 2 ++ src/smartc.ts | 5 ++--- src/typings/contractTypes.ts | 2 -- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts index b8f6eb6..388489d 100644 --- a/src/codeGenerator/astProcessor/binaryAsnProcessor.ts +++ b/src/codeGenerator/astProcessor/binaryAsnProcessor.ts @@ -106,13 +106,13 @@ export default function binaryAsnProcessor ( switch (castSide) { case 'left': if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of operator '${CurrentNode.Operation.value}'.`) + Program.Context.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of operator '${CurrentNode.Operation.value}'.`) } LGenObj = typeCasting(Program, LGenObj, rightDeclaration, CurrentNode.Operation.line) break case 'right': { if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of operator '${CurrentNode.Operation.value}'.`) + Program.Context.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of operator '${CurrentNode.Operation.value}'.`) } const oldAsm = RGenObj.asmCode RGenObj = typeCasting(Program, RGenObj, leftDeclaration, CurrentNode.Operation.line) @@ -197,7 +197,7 @@ export default function binaryAsnProcessor ( throw new Error('Internal error') case 'right': if (!(lDecl.endsWith('_ptr') && rDecl.endsWith('_ptr'))) { - Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of assignment '='.`) + Program.Context.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of assignment '='.`) } RGenObj = typeCasting(Program, RGenObj, lDecl, CurrentNode.Operation.line) } @@ -578,13 +578,13 @@ export default function binaryAsnProcessor ( switch (castSide) { case 'left': if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of comparision '${CurrentNode.Operation.value}'.`) + Program.Context.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on left side of comparision '${CurrentNode.Operation.value}'.`) } LGenObj = typeCasting(Program, LGenObj, rightDeclaration, CurrentNode.Operation.line) break case 'right': if (!(leftDeclaration.endsWith('_ptr') && rightDeclaration.endsWith('_ptr'))) { - Program.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of comparision '${CurrentNode.Operation.value}'.`) + Program.Context.warnings.push(`Warning: at line ${CurrentNode.Operation.line}. Implicit type casting conversion on right side of comparision '${CurrentNode.Operation.value}'.`) } RGenObj = typeCasting(Program, RGenObj, leftDeclaration, CurrentNode.Operation.line) } diff --git a/src/codeGenerator/codeGenerator.ts b/src/codeGenerator/codeGenerator.ts index 8c02e85..50691ef 100644 --- a/src/codeGenerator/codeGenerator.ts +++ b/src/codeGenerator/codeGenerator.ts @@ -163,7 +163,7 @@ export default function codeGenerator (Program: CONTRACT) { checkUnusedVariables() // Inspect if there were errros and throw now if (Program.Context.errors.length !== 0) { - throw new Error(Program.Context.errors + Program.warnings) + throw new Error(Program.Context.errors + Program.Context.warnings.join('\n')) } return optimizer( Program.Config.optimizationLevel, @@ -292,10 +292,10 @@ export default function codeGenerator (Program: CONTRACT) { Program.memory.forEach(Mem => { if (Mem.isSet === false) { if (Mem.scope) { - Program.warnings.push(`Warning: Unused variable '${Mem.name}' in function '${Mem.scope}'.`) + Program.Context.warnings.push(`Warning: Unused variable '${Mem.name}' in function '${Mem.scope}'.`) return } - Program.warnings.push(`Warning: Unused global variable '${Mem.name}'.`) + Program.Context.warnings.push(`Warning: Unused global variable '${Mem.name}'.`) } }) } diff --git a/src/codeGenerator/codeGeneratorTypes.ts b/src/codeGenerator/codeGeneratorTypes.ts index dc5f26b..8834bf3 100644 --- a/src/codeGenerator/codeGeneratorTypes.ts +++ b/src/codeGenerator/codeGeneratorTypes.ts @@ -23,6 +23,8 @@ export type GLOBAL_CONTEXT = { jumpId: number /** Assembly code being created */ assemblyCode: string + /** Storing warnings from compilation */ + warnings: string[] /** Errors found */ errors: string /** Current function being processed */ diff --git a/src/smartc.ts b/src/smartc.ts index c9be074..a27fc5a 100644 --- a/src/smartc.ts +++ b/src/smartc.ts @@ -68,8 +68,7 @@ export class SmartC { PCodeHashId: '', verboseAssembly: false, verboseScope: false - }, - warnings: [] + } } constructor (Options: { language: 'C' | 'Assembly', sourceCode: string }) { @@ -104,7 +103,7 @@ export class SmartC { throw new Error('Invalid usage. Language must be "C" or "Assembly".') } this.MachineCode = assembler(this.preAssemblyCode) - this.MachineCode.Warnings = this.Program.warnings.join('\n') + this.MachineCode.Warnings = this.Program.Context.warnings.join('\n') return this } diff --git a/src/typings/contractTypes.ts b/src/typings/contractTypes.ts index 42ee510..f3b9894 100644 --- a/src/typings/contractTypes.ts +++ b/src/typings/contractTypes.ts @@ -102,8 +102,6 @@ export type CONTRACT = { Config: SC_CONFIG, /** Variables and helper functions */ Context: GLOBAL_CONTEXT - /** Compilation warnings */ - warnings: string[], } export type MACHINE_OBJECT = { From d360922574f57d873d033900ce30adbd9cc66934 Mon Sep 17 00:00:00 2001 From: deleterium Date: Mon, 19 Feb 2024 23:25:36 -0300 Subject: [PATCH 5/5] refactor: Moving Context to new file --- src/codeGenerator/codeGenerator.ts | 179 +---------------------------- src/context.ts | 171 +++++++++++++++++++++++++++ src/smartc.ts | 3 + 3 files changed, 176 insertions(+), 177 deletions(-) create mode 100644 src/context.ts diff --git a/src/codeGenerator/codeGenerator.ts b/src/codeGenerator/codeGenerator.ts index 50691ef..bc1ecd9 100644 --- a/src/codeGenerator/codeGenerator.ts +++ b/src/codeGenerator/codeGenerator.ts @@ -1,6 +1,6 @@ -import { assertNotUndefined, deepCopy } from '../repository/repository' +import { assertNotUndefined } from '../repository/repository' import { CONTRACT } from '../typings/contractTypes' -import { AST, DECLARATION_TYPES, MEMORY_SLOT, SENTENCES } from '../typings/syntaxTypes' +import { AST, MEMORY_SLOT, SENTENCES } from '../typings/syntaxTypes' import optimizer from './assemblyProcessor/optimizer' import genCode from './astProcessor/genCode' @@ -17,89 +17,6 @@ type SETUPGENCODE_ARGS = { * @returns assembly source code */ export default function codeGenerator (Program: CONTRACT) { - // holds variables needed during compilation - Program.Context = { - registerInfo: [], - isTemp, - getNewRegister, - freeRegister, - latestLoopId: [], - jumpId: 0, - assemblyCode: '', - errors: '', - currFunctionIndex: -1, - currSourceLine: 0, - scopedRegisters: [], - getNewJumpID: function () { - // Any changes here, also change function auxvarsGetNewJumpID - this.jumpId++ - return this.jumpId.toString(36) - }, - getLatestLoopID: function () { - // error check must be in code! - return this.latestLoopId[this.latestLoopId.length - 1] - }, - getLatestPureLoopID: function () { - // error check must be in code! - return this.latestLoopId.reduce((previous, current) => { - if (current.includes('loop')) { - return current - } - return previous - }, '') - }, - printFreeRegisters () { - let registers = 'r0' - for (let i = 1; i < Program.Config.maxAuxVars; i++) { - if (this.scopedRegisters.findIndex(item => item === `r${i}`) === -1) { - registers += `,r${i}` - } - } - this.assemblyCode += `^comment scope ${registers}\n` - }, - startScope: function (scopeName: string) { - this.scopedRegisters.push(scopeName) - if (Program.Config.verboseScope) { - this.printFreeRegisters() - } - }, - stopScope: function (scopeName: string) { - let liberationNeeded: string - do { - liberationNeeded = assertNotUndefined(this.scopedRegisters.pop(), 'Internal error') - if (/^r\d$/.test(liberationNeeded)) { - const motherMemory = assertNotUndefined(Program.memory.find(obj => - obj.asmName === liberationNeeded && - obj.type !== 'register' - ), 'Internal error') - motherMemory.address = -1 - motherMemory.asmName = '' - const Reg = assertNotUndefined(this.registerInfo.find(Item => Item.Template.asmName === liberationNeeded)) - Reg.inUse = false - Reg.endurance = 'Standard' - } - } while (liberationNeeded !== scopeName) - if (Program.Config.verboseScope) { - this.printFreeRegisters() - } - }, - getMemoryObjectByName, - getMemoryObjectByLocation, - SentenceContext: { - isDeclaration: '', - isLeftSideOfAssignment: false, - isConstSentence: false, - isRegisterSentence: false, - hasVoidArray: false, - postOperations: '', - getAndClearPostOperations: function () { - const ret = this.postOperations - this.postOperations = '' - return ret - } - } - } - // main function for bigastCompile method, only run once. function generateMain () { // add Config Info @@ -448,98 +365,6 @@ export default function codeGenerator (Program: CONTRACT) { } } - function getMemoryObjectByName ( - varName: string, line: string, varDeclaration: DECLARATION_TYPES = '' - ) : MEMORY_SLOT { - let MemFound: MEMORY_SLOT | undefined - if (Program.Context.currFunctionIndex >= 0) { // find function scope variable - MemFound = Program.memory.find(obj => { - return obj.name === varName && obj.scope === Program.functions[Program.Context.currFunctionIndex].name - }) - } - if (MemFound === undefined) { - // do a global scope search - MemFound = Program.memory.find(obj => obj.name === varName && obj.scope === '') - } - if (MemFound === undefined) { - throw new Error(`At line: ${line}. Using variable '${varName}' before declaration.`) - } - if (MemFound.toBeRegister && MemFound.asmName === '') { - throw new Error(`At line: ${line}. Using variable '${varName}' out of scope!`) - } - if (!MemFound.isSet) { - detectAndSetNotInitialized(MemFound, line, varDeclaration !== '') - } - if (varDeclaration !== '') { // we are in declarations sentence - MemFound.isDeclared = true - return deepCopy(MemFound) - } - return deepCopy(MemFound) - } - - function getMemoryObjectByLocation (loc: number|bigint|string, line: string): MEMORY_SLOT { - let addr:number - switch (typeof loc) { - case 'number': addr = loc; break - case 'string': addr = parseInt(loc, 16); break - default: addr = Number(loc) - } - const FoundMemory = Program.memory.find(obj => obj.address === addr) - 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: string, isInitialization: boolean) { - if (Program.Context.SentenceContext.isLeftSideOfAssignment || Memory.hexContent) { - Memory.isSet = true - return - } - if (isInitialization) { - return - } - Program.warnings.push(`Warning: at line ${line}. Variable '${Memory.name}' is used but not initialized.`) - Memory.isSet = true // No more warning for same variable - } - - function isTemp (loc: number) : boolean { - if (loc === -1) return false - const id = Program.Context.registerInfo.find(OBJ => OBJ.Template.address === loc) - if (id === undefined) { - return false - } - if (Program.Context.scopedRegisters.find(items => items === id.Template.asmName)) { - // It is a register, but scoped. Do not mess!!! - return false - } - return true - } - - function getNewRegister (line: string): MEMORY_SLOT { - const id = Program.Context.registerInfo.find(OBJ => OBJ.inUse === false) - if (id === undefined) { - throw new Error(`At line: ${line}. ` + - 'No more registers available. ' + - `Increase the number with '#pragma maxAuxVars ${Program.Config.maxAuxVars + 1}' or try to reduce nested operations.`) - } - id.inUse = true - return deepCopy(id.Template) - } - - function freeRegister (loc: number|undefined): void { - if (loc === undefined || loc === -1) { - return - } - const RegInfo = Program.Context.registerInfo.find(OBJ => OBJ.Template.address === loc) - if (RegInfo === undefined) return - if (RegInfo.endurance === 'Scope') return - RegInfo.inUse = false - } - /** Run to start compilation in each sentence. */ function setupGenCode (CodeGenInfo: SETUPGENCODE_ARGS): string { CodeGenInfo.InitialAST = assertNotUndefined(CodeGenInfo.InitialAST) diff --git a/src/context.ts b/src/context.ts new file mode 100644 index 0000000..671342c --- /dev/null +++ b/src/context.ts @@ -0,0 +1,171 @@ +import { GLOBAL_CONTEXT } from './codeGenerator/codeGeneratorTypes' +import { assertNotUndefined, deepCopy } from './repository/repository' +import { CONTRACT } from './typings/contractTypes' +import { DECLARATION_TYPES, MEMORY_SLOT } from './typings/syntaxTypes' + +export function createContext (Program: CONTRACT) : GLOBAL_CONTEXT { + function detectAndSetNotInitialized (Memory: MEMORY_SLOT, line: string, isInitialization: boolean) { + if (Program.Context.SentenceContext.isLeftSideOfAssignment || Memory.hexContent) { + Memory.isSet = true + return + } + if (isInitialization) { + return + } + Program.Context.warnings.push(`Warning: at line ${line}. Variable '${Memory.name}' is used but not initialized.`) + Memory.isSet = true // No more warning for same variable + } + + return { + registerInfo: [], + isTemp (loc: number) : boolean { + if (loc === -1) return false + const id = this.registerInfo.find(OBJ => OBJ.Template.address === loc) + if (id === undefined) { + return false + } + if (this.scopedRegisters.find(items => items === id.Template.asmName)) { + // It is a register, but scoped. Do not mess!!! + return false + } + return true + }, + getNewRegister (line: string): MEMORY_SLOT { + const id = this.registerInfo.find(OBJ => OBJ.inUse === false) + if (id === undefined) { + throw new Error(`At line: ${line}. ` + + 'No more registers available. ' + + `Increase the number with '#pragma maxAuxVars ${Program.Config.maxAuxVars + 1}' or try to reduce nested operations.`) + } + id.inUse = true + return deepCopy(id.Template) + }, + freeRegister (loc: number|undefined): void { + if (loc === undefined || loc === -1) { + return + } + const RegInfo = this.registerInfo.find(OBJ => OBJ.Template.address === loc) + if (RegInfo === undefined) return + if (RegInfo.endurance === 'Scope') return + RegInfo.inUse = false + }, + latestLoopId: [], + jumpId: 0, + assemblyCode: '', + warnings: [], + errors: '', + currFunctionIndex: -1, + currSourceLine: 0, + scopedRegisters: [], + getNewJumpID: function () { + // Any changes here, also change function auxvarsGetNewJumpID + this.jumpId++ + return this.jumpId.toString(36) + }, + getLatestLoopID: function () { + // error check must be in code! + return this.latestLoopId[this.latestLoopId.length - 1] + }, + getLatestPureLoopID: function () { + // error check must be in code! + return this.latestLoopId.reduce((previous, current) => { + if (current.includes('loop')) { + return current + } + return previous + }, '') + }, + printFreeRegisters () { + let registers = 'r0' + for (let i = 1; i < Program.Config.maxAuxVars; i++) { + if (this.scopedRegisters.findIndex(item => item === `r${i}`) === -1) { + registers += `,r${i}` + } + } + this.assemblyCode += `^comment scope ${registers}\n` + }, + startScope (scopeName: string) { + this.scopedRegisters.push(scopeName) + if (Program.Config.verboseScope) { + this.printFreeRegisters() + } + }, + stopScope: function (scopeName: string) { + let liberationNeeded: string + do { + liberationNeeded = assertNotUndefined(this.scopedRegisters.pop(), 'Internal error') + if (/^r\d$/.test(liberationNeeded)) { + const motherMemory = assertNotUndefined(Program.memory.find(obj => + obj.asmName === liberationNeeded && + obj.type !== 'register' + ), 'Internal error') + motherMemory.address = -1 + motherMemory.asmName = '' + const Reg = assertNotUndefined(this.registerInfo.find(Item => Item.Template.asmName === liberationNeeded)) + Reg.inUse = false + Reg.endurance = 'Standard' + } + } while (liberationNeeded !== scopeName) + if (Program.Config.verboseScope) { + this.printFreeRegisters() + } + }, + getMemoryObjectByName ( + varName: string, line: string, varDeclaration: DECLARATION_TYPES = '' + ) : MEMORY_SLOT { + let MemFound: MEMORY_SLOT | undefined + if (this.currFunctionIndex >= 0) { // find function scope variable + MemFound = Program.memory.find(obj => { + return obj.name === varName && obj.scope === Program.functions[this.currFunctionIndex].name + }) + } + if (MemFound === undefined) { + // do a global scope search + MemFound = Program.memory.find(obj => obj.name === varName && obj.scope === '') + } + if (MemFound === undefined) { + throw new Error(`At line: ${line}. Using variable '${varName}' before declaration.`) + } + if (MemFound.toBeRegister && MemFound.asmName === '') { + throw new Error(`At line: ${line}. Using variable '${varName}' out of scope!`) + } + if (!MemFound.isSet) { + detectAndSetNotInitialized(MemFound, line, varDeclaration !== '') + } + if (varDeclaration !== '') { // we are in declarations sentence + MemFound.isDeclared = true + return deepCopy(MemFound) + } + return deepCopy(MemFound) + }, + getMemoryObjectByLocation (loc: number|bigint|string, line: string): MEMORY_SLOT { + let addr:number + switch (typeof loc) { + case 'number': addr = loc; break + case 'string': addr = parseInt(loc, 16); break + default: addr = Number(loc) + } + const FoundMemory = Program.memory.find(obj => obj.address === addr) + 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) + }, + SentenceContext: { + isDeclaration: '', + isLeftSideOfAssignment: false, + isConstSentence: false, + isRegisterSentence: false, + hasVoidArray: false, + postOperations: '', + getAndClearPostOperations: function () { + const ret = this.postOperations + this.postOperations = '' + return ret + } + } + } +} diff --git a/src/smartc.ts b/src/smartc.ts index a27fc5a..ca8a52f 100644 --- a/src/smartc.ts +++ b/src/smartc.ts @@ -8,6 +8,7 @@ import assembler from './assembler/assembler' import { PRE_TOKEN, TOKEN } from './typings/syntaxTypes' import { CONTRACT, MACHINE_OBJECT } from './typings/contractTypes' +import { createContext } from './context' /** * SmartC Compiler class. @@ -38,6 +39,7 @@ export class SmartC { private readonly sourceCode private preAssemblyCode?: string private MachineCode?: MACHINE_OBJECT + // @ts-ignore private Program: CONTRACT = { sourceLines: [], Global: { @@ -75,6 +77,7 @@ export class SmartC { this.Program.sourceLines = Options.sourceCode.split('\n') this.language = Options.language this.sourceCode = Options.sourceCode + this.Program.Context = createContext(this.Program) } /**