Created
January 13, 2022 15:44
-
-
Save s0h1s2/203a4a97dc7c24d90ddd627c1203ecb7 to your computer and use it in GitHub Desktop.
codewars assemblerInterpreter part 2 not very clean but it works
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
function isAlpha(character){ | |
return (character>='a' && character<='z' )|| (character>='A' && character<='Z') || character=='_' || isNumric(character); | |
} | |
function isNumric(character){ | |
return (character>='0' && character<='9' ); | |
} | |
function tokenizier(source) | |
{ | |
const result=[]; | |
const instuctions={ | |
'mov':true, | |
'cmp':true, | |
'msg':true, | |
'inc':true, | |
'dec':true, | |
'add':true, | |
'sub':true, | |
'mul':true, | |
'div':true, | |
'call':true, | |
'jmp':true, | |
'jne':true, | |
'je':true, | |
'jg':true, | |
'jl':true, | |
'jle':true, | |
'jge':true, | |
'ret':true, | |
'end':true | |
} | |
let start=0; | |
for(let i=0;i<source.length;i++){ | |
start=i; | |
let chr=source.charAt(i); | |
if(chr==';'){ | |
while(source.charAt(i)!='\n'){ | |
i++; | |
} | |
} | |
if(isAlpha(chr)) | |
{ | |
while(isAlpha(source.charAt(i)) && i<source.length){ | |
i++ | |
} | |
} | |
let str=source.substring(start,i); | |
if(instuctions[str]){ | |
let j=i; | |
while(source.charAt(j)!='\n' && j<source.length){ | |
j++; | |
} | |
let operands=source.substring(i,j); | |
let refactorResult=''; | |
let operandsResult=[]; | |
for(j=0;j<operands.length;j++){ | |
const currentChar=operands.charAt(j); | |
if(/^\s+$/.test(currentChar)){ | |
continue; | |
} | |
else if(currentChar=="'"){ | |
j++; | |
while(operands.charAt(j)!="'"){ | |
refactorResult+=operands.charAt(j); | |
j++; | |
} | |
}else if(currentChar==';'){ | |
break; | |
} | |
else if(currentChar==','){ | |
operandsResult.push(refactorResult); | |
refactorResult=''; | |
}else{ | |
refactorResult+=currentChar; | |
} | |
} | |
operandsResult.push(refactorResult); | |
result.push([str,...operandsResult]); | |
if(i+j<source.length){ | |
i=i+j; | |
}else{ | |
break; | |
} | |
}else{ | |
if(source.charAt(i)==':'){ | |
result.push(['label',str]); | |
} | |
} | |
} | |
return result; | |
} | |
function findLabel(instructions,label){ | |
for(let i=0;i<instructions.length;i++){ | |
if(instructions[i][0]=='label' && instructions[i][1]==label){ | |
return i; | |
} | |
} | |
} | |
function assemblerInterpreter(program) | |
{ | |
const instructions=tokenizier(program); | |
let result=''; | |
if(instructions.length==0){ | |
return ; | |
} | |
let instructionPointer=0 | |
let isCallLocked=false; | |
let previousInsturctionPointer=0; | |
const symbolTable={}; | |
let compareResult=''; | |
const compareEnum={ | |
EQ:'equal', | |
LE:'less', | |
GE:'greater' | |
}; | |
try{ | |
while(true){ | |
if(instructionPointer>instructions.length){ | |
break; | |
} | |
const currentInstruction=instructions[instructionPointer]; | |
switch(currentInstruction[0]) | |
{ | |
case 'mov': | |
if(isNaN(currentInstruction[1])){ | |
if(isNaN(currentInstruction[2])){ | |
symbolTable[currentInstruction[1]]=symbolTable[currentInstruction[2]]; | |
}else{ | |
symbolTable[currentInstruction[1]]=parseFloat(currentInstruction[2]); | |
} | |
} | |
instructionPointer++; | |
break; | |
case 'label': | |
break; | |
case 'inc':{ | |
symbolTable[currentInstruction[1]]=symbolTable[currentInstruction[1]]+1 | |
instructionPointer++; | |
break; | |
} | |
case 'dec':{ | |
symbolTable[currentInstruction[1]]=symbolTable[currentInstruction[1]]-1 | |
instructionPointer++; | |
break; | |
} | |
case 'call':{ | |
if(!isCallLocked){ | |
previousInsturctionPointer=instructionPointer; | |
isCallLocked=true; | |
} | |
const label=currentInstruction[1]; | |
instructionPointer=findLabel(instructions,label)+1; | |
break; | |
} | |
case 'ret':{ | |
if(isCallLocked){ | |
instructionPointer=previousInsturctionPointer; | |
instructionPointer++; | |
isCallLocked=false; | |
} | |
break; | |
} | |
case 'div':{ | |
const a=isNaN(currentInstruction[1])?symbolTable[currentInstruction[1]]:parseFloat(currentInstruction[1]); | |
const b=isNaN(currentInstruction[2])?symbolTable[currentInstruction[2]]:parseFloat(currentInstruction[2]); | |
if(isNaN(currentInstruction[1])){ | |
symbolTable[currentInstruction[1]]=Math.floor(a/b); | |
} | |
instructionPointer++; | |
break; | |
} | |
case 'mul':{ | |
const a=isNaN(currentInstruction[1])?symbolTable[currentInstruction[1]]:parseFloat(currentInstruction[1]); | |
const b=isNaN(currentInstruction[2])?symbolTable[currentInstruction[2]]:parseFloat(currentInstruction[2]); | |
if(isNaN(currentInstruction[1])){ | |
symbolTable[currentInstruction[1]]=a*b; | |
} | |
instructionPointer++; | |
break; | |
} | |
case 'add':{ | |
const a=isNaN(currentInstruction[1])?symbolTable[currentInstruction[1]]:parseFloat(currentInstruction[1]); | |
const b=isNaN(currentInstruction[2])?symbolTable[currentInstruction[2]]:parseFloat(currentInstruction[2]); | |
if(isNaN(currentInstruction[1])){ | |
symbolTable[currentInstruction[1]]=a+b; | |
} | |
instructionPointer++; | |
break; | |
} | |
case 'sub':{ | |
const a=isNaN(currentInstruction[1])?symbolTable[currentInstruction[1]]:parseFloat(currentInstruction[1]); | |
const b=isNaN(currentInstruction[2])?symbolTable[currentInstruction[2]]:parseFloat(currentInstruction[2]); | |
if(isNaN(currentInstruction[1])){ | |
symbolTable[currentInstruction[1]]=a-b; | |
} | |
instructionPointer++; | |
break; | |
} | |
case 'cmp':{ | |
compareResult=''; | |
const a=isNaN(currentInstruction[1])?symbolTable[currentInstruction[1]]:parseFloat(currentInstruction[1]); | |
const b=isNaN(currentInstruction[2])?symbolTable[currentInstruction[2]]:parseFloat(currentInstruction[2]); | |
if(a==b){ | |
compareResult=compareEnum.EQ; | |
} | |
else if(a<b) | |
{ | |
compareResult=compareEnum.LE | |
} | |
else | |
{ | |
compareResult=compareEnum.GE | |
} | |
instructionPointer++; | |
break; | |
} | |
case 'jmp':{ | |
const label=currentInstruction[1]; | |
instructionPointer=findLabel(instructions,label)+1; | |
break; | |
} | |
case 'je':{ | |
if(compareResult==compareEnum.EQ){ | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'jne':{ | |
if(compareResult!=compareEnum.EQ){ | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'jg':{ | |
if(compareResult==compareEnum.GE){ | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'jl':{ | |
if(compareResult==compareEnum.LE){ | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'jge':{ | |
if(compareResult==compareEnum.GE || compareResult==compareEnum.EQ){ | |
//prevInstructionPointer=instructionPointer; | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'jle':{ | |
if(compareResult==compareEnum.LE || compareResult==compareEnum.EQ){ | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'msg': | |
for(let i=1;i<currentInstruction.length;i++){ | |
if(symbolTable[currentInstruction[i]]!=undefined) | |
{ | |
result+=symbolTable[currentInstruction[i]]; | |
}else{ | |
result+=currentInstruction[i].replace(/'/g,""); | |
} | |
} | |
instructionPointer++; | |
break; | |
case 'jle':{ | |
if(compareResult==compareEnum.LE || compareResult==compareEnum.EQ){ | |
instructionPointer=findLabel(instructions,currentInstruction[1])+1; | |
}else{ | |
instructionPointer++; | |
} | |
compareResult=''; | |
break; | |
} | |
case 'end':{ | |
return result; | |
} | |
default: | |
instructionPointer++; | |
} | |
} | |
}catch(e){ | |
return -1; | |
} | |
return -1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment