Go Back   CodingForums.com > :: Client side development > JavaScript programming

Before you post, read our: Rules & Posting Guidelines

Reply
 
Thread Tools Rate Thread
Enjoy an ad free experience by logging in. Not a member yet? Register.
Old 03-04-2013, 03:58 AM   PM User | #1
jmrker
Senior Coder

 
jmrker's Avatar
 
Join Date: Aug 2006
Location: FL
Posts: 2,765
Thanks: 29
Thanked 453 Times in 447 Posts
jmrker will become famous soon enough
Smile Adding a single-step option to a loop.

The following is a "just for fun" attempt at controlling some stacks in JS.

What I would like to know is how to replace the single step logic in the
"runProgram()" function.

Currently it uses a confirm() command, but I would like to use something
else to single-step through the stack actions.
It causes the screen to darken and put an obtrusive box in the middle of the screen.

Any recommended changes are welcome.

Code:
<!DOCTYPE HTML>
<html>
<head>
<title> Stack Test </title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

<style type="text/css">
 #stackDisplay {
  height:100px; width:200px; overflow:auto; margin: 0px 5px;
   background-color:yellow; float:left; border:1px solid black;
 }
 #operandDisplay {
  height:100px; width:200px; overflow:auto; margin: 0px 5px;
  background-color:cyan; float:left; border:1px solid black;
 }
 #program {
  height:100px; width:200px;  margin: 0px 5px;
  background-color:lightblue; float:left; border:1px solid black;
 }
</style>

</head>
<body>
<div id="stackDisplay"></div>
<div id="operandDisplay"></div>
<textarea id="program"></textarea>
<br style="clear:both">

<input type="checkbox" id="SStep"> Single Step <button onclick="runProgram()">Run</button>

<script type="text/javascript">
function $_(IDS) { return document.getElementById(IDS); }

var TOS = NOS = act = 0;       // TOS=TopOfStack, NOS=NextOnStack
var stack = [];       var operand = [];

function runProgram() {
  TOS = NOS = act = 0;       // TOS=TopOfStack, NOS=NextOnStack
  stack = [];  operand = [];
  $_('stackDisplay').innerHTML = '';
  $_('operandDisplay').innerHTML = '';
  strToTokens($_('program').value);
  var flag = true;
  while (((operand.length) > 0) && (flag)) {
    act = operand.shift();
    if ('*/+-'.indexOf(act) != -1) { Act2Stack(act) }
    if ('dup,swap,drop'.indexOf(act) != -1) { Act1Stack(act); }
    showStacks();
    if ($_('SStep').checked) { flag = confirm('Next'); }
  }
}  

function strToTokens(str) {
  var arr = str.split(' ');
  for (var i=0; i<arr.length; i++) {
    if (isNaN(arr[i])) { operand.push(arr[i]); }
                  else { stack.push(arr[i]); }
  }
}
function showStacks() {
  $_('stackDisplay').innerHTML = stack.join('<br>');
  $_('operandDisplay').innerHTML = operand.join('<br>');
  return true;
}

function Act1Stack(act) {
  var tmp;
  switch (act) {
    case 'dup'  : stack.unshift(stack[stack.length-1]); break; 
    case 'swap' : tmp = stack.shift(); TOS = stack.shift();
                  stack.unshift(tmp); stack.unshift(TOS); break; 
    case 'drop' : tmp = stack.shift(); break;
  }
}
function Act2Stack(act) {
  TOS = stack.shift()*1;
  NOS = stack.shift()*1;
  switch (act) {
    case '*' : TOS = TOS * NOS; break;
    case '/' : TOS = TOS / NOS; break;
    case '+' : TOS = TOS + NOS; break;
    case '-' : TOS = TOS - NOS; break;
  } stack.unshift(TOS);
}

// Testing program 
var str = '';
    str = '123 45 + 3 / 3 - -1 * drop\n';     // -53
    str += '123 45 swap - 3 / 3 + -1 * dup';  //  23
    $_('program').value = str.replace(/\n/g,' ');

</script>

</body>
</html>
jmrker is offline   Reply With Quote
Old 03-04-2013, 06:44 AM   PM User | #2
Dormilich
Senior Coder

 
Dormilich's Avatar
 
Join Date: Jan 2010
Location: Behind the Wall
Posts: 2,882
Thanks: 9
Thanked 291 Times in 287 Posts
Dormilich is on a distinguished road
If it were not switchable, I’d just use something like an iterator (similar to the PHP Iterators) where you tie the call to next() to a button click event.
__________________
please post your code wrapped in [CODE] [/CODE] tags
Dormilich is offline   Reply With Quote
Old 03-04-2013, 07:38 AM   PM User | #3
felgall
Master Coder

 
felgall's Avatar
 
Join Date: Sep 2005
Location: Sydney, Australia
Posts: 5,465
Thanks: 0
Thanked 499 Times in 491 Posts
felgall is a jewel in the roughfelgall is a jewel in the roughfelgall is a jewel in the rough
You could override the built in confirm function with your own version that does what you want it to do.
__________________
Stephen
Learn Modern JavaScript - http://javascriptexample.net/
Helping others to solve their computer problem at http://www.felgall.com/
felgall is offline   Reply With Quote
Old 03-04-2013, 07:40 AM   PM User | #4
Airblader
Regular Coder

 
Join Date: Jan 2013
Location: Germany
Posts: 368
Thanks: 3
Thanked 44 Times in 44 Posts
Airblader can only hope to improve
I may be wrong, but I think the question was more about how to "pause" the loop so that the user can see what's going on(?). If that's so, the question just depends on how you want to present it to the user. You could use a timeout (which would give the user only a certain time, no confirmation feedback needed/possible) or you could use a "Next Step" button, which I'd prefer.
If you use a button, you can pretty much get rid of the loop altogether and simply reduce it to an if statement.

By the way: If you need comments to explain what variables are for, you are likely to have named them wrong. Just name them "topofStack" and "nextOnStack" – you can remove pointcless, repeated comments and make the code more readable.
Airblader is offline   Reply With Quote
Old 03-04-2013, 07:57 AM   PM User | #5
Philip M
Supreme Master coder!

 
Philip M's Avatar
 
Join Date: Jun 2002
Location: London, England
Posts: 17,044
Thanks: 197
Thanked 2,412 Times in 2,390 Posts
Philip M has a spectacular aura aboutPhilip M has a spectacular aura aboutPhilip M has a spectacular aura about
Quote:
Originally Posted by Airblader View Post
By the way: If you need comments to explain what variables are for, you are likely to have named them wrong. Just name them "topofStack" and "nextOnStack" – you can remove pointcless, repeated comments and make the code more readable.
I am afraid that I do not agree. TOS and NOS seem eminently appropriate abbreviations to me, as the comments explain them very clearly.

TOS (or topOfStack) occurs 11 times in the code. Apart from the extra typing required (77 characters) there arises the risk of typo errors such as topofStack instead of topOfStack. (Assuming you want consistency with NextOnStack). Not pointcless at all.
__________________

All the code given in this post has been tested and is intended to address the question asked.
Unless stated otherwise it is not just a demonstration.
Philip M is offline   Reply With Quote
Old 03-04-2013, 05:35 PM   PM User | #6
Airblader
Regular Coder

 
Join Date: Jan 2013
Location: Germany
Posts: 368
Thanks: 3
Thanked 44 Times in 44 Posts
Airblader can only hope to improve
If you care about a few characters, there is always minification I'd rather have my code document itself than having to document it manually, which introduces the risk of rotting comments that are incomplete, not precise and ultimatively simply wrong. Risks, that my IDE cannot protect me from – unlike typos which are virtually inexistent these days with code-completion and all that stuff.

Comments, if used, should explain the code, not explain the name I'm giving to variables. And If it wasn't for the comments, it would've at least taken me some time to figure out what NOS and TOS are meant to represent.

Quote:
A comment that has gotten old, irrelevant, and incorrect is obsolete. Comments get old quickly. It is best not to write a comment that will become obsolete. If you find an obsolete comment, it is best to update it or get rid of it as quickly as possible. Obsolete comments tend to migrate away from the code they once described. They become floating islands of irrelevance and misdirection in the code. – Robert C. Martin
(Source)

Quote:
If a name requires a comment; change the name
(Source, slide 5 of 43)

However, I know that to an extent this is a matter of habit and taste. By the way, Philip, I know you're not a friend of lengthy names. I wonder what you'd think if you were to read through our code at work with test function names like

Code:
@Test
public void givenSomeDescriptionOfTheScenarioWhenSomeActionIsTakenThenCompareInputAndOutputToHaveTheExpectedValuesAndStructure () { 
   [...] 
}
(Edit: Maybe I should add that I'm not exactly a fan of these super-long names either, but they tend to be really useful when debugging tests)

And you don't need to be afraid to disagree. I, for once, could live with both naming methods. I was just pointing out my preferences. Descriptive names versus too long names sure isn't always an easy topic for me either.

Last edited by Airblader; 03-04-2013 at 05:39 PM..
Airblader is offline   Reply With Quote
Old 03-04-2013, 07:20 PM   PM User | #7
Philip M
Supreme Master coder!

 
Philip M's Avatar
 
Join Date: Jun 2002
Location: London, England
Posts: 17,044
Thanks: 197
Thanked 2,412 Times in 2,390 Posts
Philip M has a spectacular aura aboutPhilip M has a spectacular aura aboutPhilip M has a spectacular aura about
Quote:
Originally Posted by Airblader View Post
(Edit: Maybe I should add that I'm not exactly a fan of these super-long names either, but they tend to be really useful when debugging tests)

And you don't need to be afraid to disagree. I, for once, could live with both naming methods. I was just pointing out my preferences. Descriptive names versus too long names sure isn't always an easy topic for me either.
Same as before. You work in an environment where other people have to understand your code with ease, and perhaps modify it, and vice-versa. The only person who has to understand my code is myself.

My policy is that names should be short, as short as is convenient, but still meaningful. Say uname for user name, dy for day and mth for month, but still pretty obvious. Not something impenetrable like a, fred or xyz. I don't indent for the reason I have already explained, but usually leave blank lines before/after loops, between functions etc. I grew up in an environment where variable names had to be as short as possible to save precious bytes - you could not afford lengthy names such as your test functions.
__________________

All the code given in this post has been tested and is intended to address the question asked.
Unless stated otherwise it is not just a demonstration.
Philip M is offline   Reply With Quote
Old 03-05-2013, 04:59 PM   PM User | #8
jmrker
Senior Coder

 
jmrker's Avatar
 
Join Date: Aug 2006
Location: FL
Posts: 2,765
Thanks: 29
Thanked 453 Times in 447 Posts
jmrker will become famous soon enough
Thumbs up

@Airblader: Thank you. The change to an if statement did the trick. I was able to view the changes without the shading and placement of the alert message.

@Philip M: Thank you for the short variable name defense. I, too, was brought up in an environment of limited memory.
So long as the variable name is defined (commented?) somewhere, I have no problems understanding the meaning.

The longer variable names are useful and I can see the benefit of their use in more complicated programs.
MY problem with them is it gives me more opportunities to make spelling mistakes.

This was just an attempt at a FORTH style language using javascript as a RPN calculator, so for that reason I was keeping the variable names short.

@felgall: Would you have a short example of how a function could be created to overwrite the confirmation function?
I tried something like that but could not figure out how to use it without an infinite pause waiting for the operator to enter something.

My current logic for the single-step action was a change along this line...
Code:
var SSflag = false;
function RUN() {
  if ( !SSflag ) {
    TOS = NOS = act = 0;
    stack = [];  operand = [];
    $_('stackDisplay').innerHTML = '';
    $_('operandDisplay').innerHTML = '';
    strToTokens($_('program').value);
  } runProgram();
}
function runProgram() {
  if ($_('SStep').checked) { SSflag = true;
    if ((stack.length > 0) && (operand.length >= 0)) {
      showStacks();  act = operand.shift();  takeAction(act);
    } else { alert('End of Program'); } // SSflag = false;}
  } else {  SSflag = false;    // run program at full speed
    while (operand.length > 0) { takeAction(operand.shift()); }  showStacks();
  }
}
I can provide the rest of the code for anyone interested, but the crux of the probem (single step vs full speed)
is solved in the runProgram() function above.
jmrker is offline   Reply With Quote
Reply

Bookmarks

Jump To Top of Thread


Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 02:04 AM.


Advertisement
Log in to turn off these ads.