Skip to content

Instantly share code, notes, and snippets.

@s0h1s2
Created January 13, 2022 15:44
Show Gist options
  • Save s0h1s2/203a4a97dc7c24d90ddd627c1203ecb7 to your computer and use it in GitHub Desktop.
Save s0h1s2/203a4a97dc7c24d90ddd627c1203ecb7 to your computer and use it in GitHub Desktop.
codewars assemblerInterpreter part 2 not very clean but it works
"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