Execute SNUSP/Java: Difference between revisions
(Added % command) |
m (Fixed syntax highlighting.) |
||
(13 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
{{implementation|SNUSP}}{{collection|RCSNUSP}} |
{{implementation|SNUSP}}{{collection|RCSNUSP}} |
||
This implementation has all of the basic characters plus '%', '@', and '#' (characters from modular and bloated SNUSP found on [ |
This [[Java]] implementation has all of the basic characters plus '<code>%</code>', '<code>@</code>', and '<code>#</code>' (characters from modular and bloated SNUSP found on [[eso:SNUSP|esolangs]]). The memory space grows to the right as needed, and the memory pointer cannot go negative. The program will exit if the memory pointer moves to a negative value or if the code pointer leaves the code space. The input ignores return characters because of the way <tt>BufferedReader</tt> is set up. The random command places a random ASCII value (code 0 through the value in the cell inclusive) in the current memory space. |
||
The implementation comes in two classes: the main program and a code pointer class. The separation is for the easier addition of '&' (split) which could come in the future (the code pointer class would only need to extend <tt>Thread</tt> and code added to deal with the command). The main class decides on the input method (file or std in), reads the code, and starts the code pointer. It also figures out where the starting point in the code is ('$').<br clear=all> |
The implementation comes in two classes: the main program and a code pointer class. The separation is for the easier addition of '<code>&</code>' (split) which could come in the future (the code pointer class would only need to extend <tt>Thread</tt> and code would need to be added to deal with the command). The main class decides on the input method (file or std in), reads the code, and starts the code pointer. It also figures out where the starting point in the code is ('<code>$</code>' or 0,0).<br clear=all> |
||
{{works with|Java|1.5+}} |
{{works with|Java|1.5+}} |
||
⚫ | |||
The main class: |
|||
⚫ | |||
import java.io.BufferedReader; |
import java.io.BufferedReader; |
||
import java.io.FileNotFoundException; |
import java.io.FileNotFoundException; |
||
Line 47: | Line 49: | ||
return code; |
return code; |
||
} |
} |
||
}</syntaxhighlight> |
|||
The code pointer class: |
|||
}</java> |
|||
<syntaxhighlight lang="java5">import java.awt.Point; |
|||
import java.io.BufferedReader; |
import java.io.BufferedReader; |
||
import java.io.IOException; |
import java.io.IOException; |
||
Line 55: | Line 57: | ||
import java.util.ArrayList; |
import java.util.ArrayList; |
||
import java.util.LinkedList; |
import java.util.LinkedList; |
||
import java.util.Random; |
|||
public class CodePtr{ |
public class CodePtr{ |
||
⚫ | |||
final int LEFT= 2, RIGHT= 0, UP= 3, DOWN= 1;//directions |
|||
static final Random rand = new Random(); |
|||
⚫ | |||
ArrayList<String> code;//code array |
ArrayList<String> code;//code array |
||
Direction dir;//current direction |
|||
ArrayList<Character> mem;//memory space |
ArrayList<Character> mem;//memory space |
||
int memPtr;//memory pointer |
int memPtr;//memory pointer |
||
Point place;//code pointer |
Point place;//code pointer |
||
LinkedList<Point> pStack;//code pointer stack |
LinkedList<Point> pStack;//code pointer stack |
||
LinkedList< |
LinkedList<Direction> dStack;//direction stack |
||
//input stream |
//input stream |
||
BufferedReader input= new BufferedReader(new InputStreamReader(System.in)); |
BufferedReader input= new BufferedReader(new InputStreamReader(System.in)); |
||
public CodePtr( |
public CodePtr(ArrayList<String> code, Point place){ |
||
this.code= code; |
this.code= code; |
||
dir= RIGHT; |
dir= Direction.RIGHT; |
||
this.place= place; |
this.place= place; |
||
mem = new ArrayList<Character>(); |
mem = new ArrayList<Character>(); |
||
mem.add('\0');//initial memory |
mem.add('\0');//initial memory |
||
memPtr= 0; |
memPtr= 0; |
||
dStack= new LinkedList< |
dStack= new LinkedList<Direction>(); |
||
pStack= new LinkedList<Point>(); |
pStack= new LinkedList<Point>(); |
||
} |
} |
||
public CodePtr( |
public CodePtr(Point place, Direction dir){ |
||
//This constructor is left over from attempts at '&' |
|||
this.dir= dir; |
this.dir= dir; |
||
this.place= place; |
this.place= place; |
||
Line 86: | Line 90: | ||
public void run(){ |
public void run(){ |
||
place= moveCP(); |
for(;execute(code.get(place.y).charAt(place.x));place= moveCP()); |
||
while(execute(code.get(place.y).charAt(place.x))){ |
|||
place= moveCP(); |
|||
} |
|||
} |
} |
||
private boolean execute( |
private boolean execute(char inst){ |
||
//ignore char and keep going |
//ignore char and keep going |
||
if(!instChars.contains("" + inst)) return true; |
if(!instChars.contains("" + inst)) return true; |
||
Line 102: | Line 103: | ||
try{ |
try{ |
||
int in; |
int in; |
||
while((in= input.read()) == |
while((in= input.read()) == '\n' || in == '\r');//skip return chars |
||
mem.set(memPtr, (char)in); |
mem.set(memPtr, (char)in); |
||
}catch(final IOException e){ |
}catch(final IOException e){ |
||
Line 112: | Line 113: | ||
break; |
break; |
||
case '?'://conditional skip |
case '?'://conditional skip |
||
if(mem.get(memPtr) == 0) place= moveCP(); |
if(mem.get(memPtr) == '\0') place= moveCP(); |
||
break; |
break; |
||
case '>'://move pointer right |
case '>'://move pointer right |
||
Line 130: | Line 131: | ||
switch(dir){ |
switch(dir){ |
||
case RIGHT: |
case RIGHT: |
||
dir= UP; |
dir= Direction.UP; |
||
break; |
break; |
||
case DOWN: |
case DOWN: |
||
dir= LEFT; |
dir= Direction.LEFT; |
||
break; |
break; |
||
case LEFT: |
case LEFT: |
||
dir= DOWN; |
dir= Direction.DOWN; |
||
break; |
break; |
||
case UP: |
case UP: |
||
dir= RIGHT; |
dir= Direction.RIGHT; |
||
break; |
break; |
||
default: |
default: |
||
Line 147: | Line 148: | ||
switch(dir){ |
switch(dir){ |
||
case RIGHT: |
case RIGHT: |
||
dir= DOWN; |
dir= Direction.DOWN; |
||
break; |
break; |
||
case DOWN: |
case DOWN: |
||
dir= RIGHT; |
dir= Direction.RIGHT; |
||
break; |
break; |
||
case LEFT: |
case LEFT: |
||
dir= UP; |
dir= Direction.UP; |
||
break; |
break; |
||
case UP: |
case UP: |
||
dir= LEFT; |
dir= Direction.LEFT; |
||
break; |
break; |
||
default: |
default: |
||
Line 169: | Line 170: | ||
case '#'://pop |
case '#'://pop |
||
if(dStack.size() > 0){ |
if(dStack.size() > 0){ |
||
Direction oldDir= dStack.pop(); |
|||
Point oldPlace= pStack.pop(); |
|||
place= oldPlace; |
place= oldPlace; |
||
dir= oldDir; |
dir= oldDir; |
||
Line 183: | Line 184: | ||
break; |
break; |
||
case '%': |
case '%': |
||
⚫ | |||
//use a random regular ASCII character |
|||
break; |
|||
⚫ | |||
default: |
default: |
||
} |
} |
||
Line 208: | Line 209: | ||
} |
} |
||
if(retVal.x<0 || retVal.y<0 || |
if(retVal.x<0 || retVal.y<0 || |
||
retVal.y >= code.size() || retVal.x >= code.get(0).length()){ |
|||
retVal.x >= code.get(0).length()){ |
|||
System.err.println("Code pointer has left the code space"); |
System.err.println("Code pointer has left the code space"); |
||
System.exit(-1); |
System.exit(-1); |
||
Line 215: | Line 215: | ||
return retVal; |
return retVal; |
||
} |
} |
||
private enum Direction{ |
|||
}</java> |
|||
UP,DOWN,LEFT,RIGHT; |
|||
} |
|||
}</syntaxhighlight> |
Latest revision as of 09:02, 1 September 2022
This Java implementation has all of the basic characters plus '%
', '@
', and '#
' (characters from modular and bloated SNUSP found on esolangs). The memory space grows to the right as needed, and the memory pointer cannot go negative. The program will exit if the memory pointer moves to a negative value or if the code pointer leaves the code space. The input ignores return characters because of the way BufferedReader is set up. The random command places a random ASCII value (code 0 through the value in the cell inclusive) in the current memory space.
The implementation comes in two classes: the main program and a code pointer class. The separation is for the easier addition of '&
' (split) which could come in the future (the code pointer class would only need to extend Thread and code would need to be added to deal with the command). The main class decides on the input method (file or std in), reads the code, and starts the code pointer. It also figures out where the starting point in the code is ('$
' or 0,0).
The main class:
import java.awt.Point;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
public class SNUSP{
static Point start;
public static void main(String[] args){
try{
start= new Point(0,0);
BufferedReader in;
ArrayList<String> code = new ArrayList<String>();
if(args.length > 0){
in= new BufferedReader(new FileReader(args[0]));
}else{
in= new BufferedReader(new InputStreamReader(System.in));
}
code= parse(in);
CodePtr cp = new CodePtr(code, start);
cp.run();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
private static ArrayList<String> parse(BufferedReader in)
throws IOException{
String line;
ArrayList<String> code= new ArrayList<String>();
while((line= in.readLine())!=null){
code.add(line);
if(line.contains("$")){
start = new Point(line.indexOf('$'), code.size() - 1);
}
}
return code;
}
}
The code pointer class:
import java.awt.Point;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;
public class CodePtr{
static final String instChars= "><.,/\\+-#@$%!?";//valid chars
static final Random rand = new Random();
ArrayList<String> code;//code array
Direction dir;//current direction
ArrayList<Character> mem;//memory space
int memPtr;//memory pointer
Point place;//code pointer
LinkedList<Point> pStack;//code pointer stack
LinkedList<Direction> dStack;//direction stack
//input stream
BufferedReader input= new BufferedReader(new InputStreamReader(System.in));
public CodePtr(ArrayList<String> code, Point place){
this.code= code;
dir= Direction.RIGHT;
this.place= place;
mem = new ArrayList<Character>();
mem.add('\0');//initial memory
memPtr= 0;
dStack= new LinkedList<Direction>();
pStack= new LinkedList<Point>();
}
public CodePtr(Point place, Direction dir){
//This constructor is left over from attempts at '&'
this.dir= dir;
this.place= place;
}
public void run(){
for(;execute(code.get(place.y).charAt(place.x));place= moveCP());
}
private boolean execute(char inst){
//ignore char and keep going
if(!instChars.contains("" + inst)) return true;
switch(inst){
case '.'://print
System.out.print(mem.get(memPtr));
break;
case ','://input
try{
int in;
while((in= input.read()) == '\n' || in == '\r');//skip return chars
mem.set(memPtr, (char)in);
}catch(final IOException e){
e.printStackTrace();
}
break;
case '!'://skip
place= moveCP();
break;
case '?'://conditional skip
if(mem.get(memPtr) == '\0') place= moveCP();
break;
case '>'://move pointer right
memPtr++;
while(mem.size() <= memPtr){
mem.add('\0');//add more memory cells if necessary
}
break;
case '<'://move memory pointer left
memPtr--;
if(memPtr < 0){//no negative values
System.err.println("memory pointer out of range (negative)");
return false;//stop executing
}
break;
case '/'://mirror
switch(dir){
case RIGHT:
dir= Direction.UP;
break;
case DOWN:
dir= Direction.LEFT;
break;
case LEFT:
dir= Direction.DOWN;
break;
case UP:
dir= Direction.RIGHT;
break;
default:
}
break;
case '\\'://mirror
switch(dir){
case RIGHT:
dir= Direction.DOWN;
break;
case DOWN:
dir= Direction.RIGHT;
break;
case LEFT:
dir= Direction.UP;
break;
case UP:
dir= Direction.LEFT;
break;
default:
}
break;
case '+'://inc
mem.set(memPtr, (char)(mem.get(memPtr) + 1));
break;
case '-'://dec
mem.set(memPtr, (char)(mem.get(memPtr) - 1));
break;
case '#'://pop
if(dStack.size() > 0){
Direction oldDir= dStack.pop();
Point oldPlace= pStack.pop();
place= oldPlace;
dir= oldDir;
return true;
}
return false;
case '@'://push
//protect the reference with a new object
pStack.push(new Point(place));
dStack.push(dir);
place= moveCP();//skip
break;
case '%':
mem.set(memPtr, (char)rand.nextInt(mem.get(memPtr) + 1));
break;
default:
}
return true;
}
private Point moveCP(){
final Point retVal= new Point(place);
switch(dir){
case RIGHT:
retVal.x++;
break;
case DOWN:
retVal.y++;
break;
case LEFT:
retVal.x--;
break;
case UP:
retVal.y--;
break;
default:
}
if(retVal.x<0 || retVal.y<0 ||
retVal.y >= code.size() || retVal.x >= code.get(0).length()){
System.err.println("Code pointer has left the code space");
System.exit(-1);
}
return retVal;
}
private enum Direction{
UP,DOWN,LEFT,RIGHT;
}
}