diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md
index ed4f39a..06f56ef 100644
--- a/.github/CONTRIBUTING.md
+++ b/.github/CONTRIBUTING.md
@@ -7,20 +7,24 @@ so **be careful** on what you're doing!
Read our [Code of Conduct](./CODE_OF_CONDUCT.md) to keep our community approachable and respectable.
-Use the table of contents icon on the top left corner of this document to get to a specific section of this guide quickly.
+---
-## New contributor guide
+## Contributing code
-To get an overview of the project, check out our [README](README.md).
+### Before contributing
-Here are some resources to help you get started with open source contributions:
+You must know this before contributing:
-- [Finding ways to contribute to open source on GitHub](https://docs.github.com/en/get-started/exploring-projects-on-github/finding-ways-to-contribute-to-open-source-on-github)
-- [Set up Git](https://docs.github.com/en/get-started/quickstart/set-up-git)
-- [GitHub flow](https://docs.github.com/en/get-started/quickstart/github-flow)
-- [Collaborating with pull requests](https://docs.github.com/en/github/collaborating-with-pull-requests)
+- Your contribution might be rejected for considerable reason(s).
+- Your submitted code might be or will be ___ with or without you knowing.
+ - removed within the bounds of the project
+ - modified as needed or as necessary
+ - moved within the bounds of the project
+ - copied within the bounds of the project
+- You will be known as a contributor of this repository.
+- You might be called out to fix a bug created by your code if necessary.
-To give us a suggestion on what utility to do next, you can open up an [issue](https://github.com/JumperBot/Unsafe-4-Bit/issues/new/choose).
+---
### How to start writing "the" code
@@ -38,6 +42,8 @@ The first and most important step is getting to know yourself and your setup:
Next step would be ***\*drum-roll\**** forking the repository!
- You can now write the actual code.
+---
+
### What to do when writing the code
- Make the code **concise**.
@@ -48,6 +54,8 @@ Next step would be ***\*drum-roll\**** forking the repository!
- Take a look at some of the files to know what I meant by that.
- Never forget to **test and compile** the code first on your machine before such reckless moves!
+---
+
### What to do after writing the code
- Check, test and compile your code into it's appropriate directory.
@@ -57,14 +65,18 @@ Next step would be ***\*drum-roll\**** forking the repository!
- Fill up the form!
- Wait for me to accept your changes!
+---
+
## Issues
-### Create a new issue
+### Creating a new issue
If you spotted a problem or would like to create a new issue, [search if an issue already exists](https://docs.github.com/en/github/searching-for-information-on-github/searching-on-github/searching-issues-and-pull-requests#search-by-the-title-body-or-comments).
If a related issue doesn't exist, you can open a new issue using a relevant [issue form](https://github.com/JumperBot/Unsafe-4-Bit/issues/new/choose).
+---
+
### Solve an issue
Scan through our [existing issues](https://github.com/JumperBot/Unsafe-4-Bit/issues) to find one that interests you.
diff --git a/README.md b/README.md
index 06edfda..5d83393 100644
--- a/README.md
+++ b/README.md
@@ -92,7 +92,7 @@ and [compile](./src/README.md#UFBC) and [run](./src/README.md#UFB) the program!
/*
Write "Hello World" to memory index: 38
*/
-wvar 38 8 5 12 12 15 0 23 15 18 12 4
+wvar 38 "Hello World"
// Print the variable residing in memory index: 38
print 38
/* Jump to command no. 0
diff --git a/build/README.md b/build/README.md
index 4dad4b8..dc70f04 100644
--- a/build/README.md
+++ b/build/README.md
@@ -37,7 +37,7 @@ java -jar UFB.jar [ -flags ] [ file ]
---
-## Example
+## Examples
```shell
java UFB -pnv
@@ -47,4 +47,5 @@ java UFB -nvp
java UFB -pnhv
java UFB -mn
java UFB -c ../test/UFB/Main.ufb
+java UFB -b ../test/UFB/Main.ufbb
```
\ No newline at end of file
diff --git a/build/UFB.jar b/build/UFB.jar
index c2f7a3e..27594bd 100644
Binary files a/build/UFB.jar and b/build/UFB.jar differ
diff --git a/build/UFB/FlagManager.class b/build/UFB/FlagManager.class
index 18b595a..e39b02c 100644
Binary files a/build/UFB/FlagManager.class and b/build/UFB/FlagManager.class differ
diff --git a/build/UFB/Optimizer$1.class b/build/UFB/Optimizer$1.class
index caca535..85369d2 100644
Binary files a/build/UFB/Optimizer$1.class and b/build/UFB/Optimizer$1.class differ
diff --git a/build/UFB/Optimizer.class b/build/UFB/Optimizer.class
index a1ee0b4..71b9bb9 100644
Binary files a/build/UFB/Optimizer.class and b/build/UFB/Optimizer.class differ
diff --git a/build/UFB/Runner$1.class b/build/UFB/Runner$1.class
new file mode 100644
index 0000000..aad50c4
Binary files /dev/null and b/build/UFB/Runner$1.class differ
diff --git a/build/UFB/Runner.class b/build/UFB/Runner.class
index b4bd570..24e58c8 100644
Binary files a/build/UFB/Runner.class and b/build/UFB/Runner.class differ
diff --git a/build/UFB/UFB.class b/build/UFB/UFB.class
index bcaa50e..fbfcc34 100644
Binary files a/build/UFB/UFB.class and b/build/UFB/UFB.class differ
diff --git a/build/UFB/UFBC$1.class b/build/UFB/UFBC$1.class
index 2d5b7e4..35240e0 100644
Binary files a/build/UFB/UFBC$1.class and b/build/UFB/UFBC$1.class differ
diff --git a/build/UFB/UFBC$2.class b/build/UFB/UFBC$2.class
new file mode 100644
index 0000000..eb8b50b
Binary files /dev/null and b/build/UFB/UFBC$2.class differ
diff --git a/build/UFB/UFBC.class b/build/UFB/UFBC.class
index a0e512b..eec8cb5 100644
Binary files a/build/UFB/UFBC.class and b/build/UFB/UFBC.class differ
diff --git a/build/build.sh b/build/build.sh
index 634b8c1..492e83d 100644
--- a/build/build.sh
+++ b/build/build.sh
@@ -1,9 +1,11 @@
#!/bin/sh
cd UFB
-javac -verbose ../../src/UFB/*.java -d .
-echo
-jar --create --file=../UFB.jar --verbose --main-class=UFB *.class
+echo "javac ../../src/UFB/*.java -d . -Xdiags:verbose"
+javac ../../src/UFB/*.java -d . -Xdiags:verbose
+echo "jar --create --file=../UFB.jar --main-class=UFB *.class"
+jar --create --file=../UFB.jar --main-class=UFB *.class
cd ..
# Copy build/README.md to src/README.md
-cp README.md ../src/README.md
\ No newline at end of file
+echo "cp README.md ../src/README.md"
+cp README.md ../src/README.md
diff --git a/src/README.md b/src/README.md
index 4dad4b8..dc70f04 100644
--- a/src/README.md
+++ b/src/README.md
@@ -37,7 +37,7 @@ java -jar UFB.jar [ -flags ] [ file ]
---
-## Example
+## Examples
```shell
java UFB -pnv
@@ -47,4 +47,5 @@ java UFB -nvp
java UFB -pnhv
java UFB -mn
java UFB -c ../test/UFB/Main.ufb
+java UFB -b ../test/UFB/Main.ufbb
```
\ No newline at end of file
diff --git a/src/UFB/FlagManager.java b/src/UFB/FlagManager.java
index d89857c..60fab4f 100644
--- a/src/UFB/FlagManager.java
+++ b/src/UFB/FlagManager.java
@@ -24,16 +24,38 @@
class FlagManager{
final String flagString="[pnmvhclb]";
+ final String[] longFlagsArr={
+ "unoptimized"
+ };
final boolean[] isActivated=new boolean[flagString.length()-2];
+ final boolean[] isLongActivated=new boolean[longFlagsArr.length];
final String file;
- final Pattern flags=Pattern.compile(flagString);
- final Pattern repeats=Pattern.compile("(\\w)\\1+");
public FlagManager(final String[]a){
+ final Pattern flags=Pattern.compile(flagString);
+ final Pattern longFlags=Pattern.compile(
+ Arrays.toString(longFlagsArr).substring(1)
+ .replaceAll("\\]$", "")
+ .replace(", ", "|")
+ );
+ final Pattern repeats=Pattern.compile("(\\w)\\1+");
+ final Pattern doubleHyphens=Pattern.compile("^-+");
String fileName="";
for(final String s:a){
final String arg=s.trim();
if(arg.endsWith(".ufbb")||arg.endsWith(".ufb"))fileName=arg;
- else if(arg.startsWith("-")){
+ else if(arg.startsWith("--")){
+ final String arg2=doubleHyphens.matcher(arg).replaceAll("");
+ if(longFlags.matcher(arg2).matches()){
+ for(int i=0;i.
- *
-**/
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileWriter;
-
-import java.util.HashMap;
-
-class Optimizer{
- final char[] mem=new char[256];
- final int[] memInd=new int[256];
- final boolean[] aKnownNonNum=new boolean[256];
- final BufferedInputStream buffer;
- final int size;
- final int[] lines;
- int furthestLine=-1;
- final StringBuilder printProxy=new StringBuilder();
- final StringBuilder newCommands=new StringBuilder();
- public Optimizer(final String file)throws Exception{
- mem[0]=' ';
- aKnownNonNum[0]=true;
- for(int i=0;i<26;i++){
- final int ind=i+1;
- aKnownNonNum[ind]=true;
- mem[ind]=(char)(ind+64);
- }
- for(int i=0;i<10;i++)mem[i+27]=String.valueOf(i).charAt(0);
- mem[37]='\n';
- for(int i=37;i<256;i++)aKnownNonNum[i]=true;
- final File f=new File(file);
- buffer=new BufferedInputStream(new FileInputStream(f));
- buffer.mark(Integer.MAX_VALUE);
- size=(int)f.length();
- lines=new int[size];
- try{
- run();
- buffer.close();
- final String newFileName=file.substring(0, file.lastIndexOf("."))+".optimized.ufb";
- final File newGenCode=new File(newFileName);
- try(final FileWriter writer=new FileWriter(newGenCode)){
- writer.write(newCommands.append("\nnvar 38").toString().trim().replaceAll("\n{2,}", "\n"));
- }
- UFBC.compile(newFileName, false);
- newGenCode.delete();
- new File(file).delete();
- final File newCompiledFile=new File(newFileName+"b");
- newCompiledFile.renameTo(new File(file));
- }catch(final Exception e){
- buffer.close();
- if(!e.toString().contains("Code cannot be optimized"))throw new RuntimeException(e);
- else System.out.println("Code cannot be optimized, but compilation is a success!");
- }
- }
- private void addToCommands(){
- final String converted=convertToMemory(
- printProxy.toString() // i == -255, - == -254, . == -253
- ).replace("-255", "\nwvar 38 27\ndiv 38 27\nprint 38\nprint 255")
- .replace("-254", "\nwvar 38 27\nsub 38 28\ntrim 38 1\nprint 38\nprint 255")
- .replace("-253", "\nwvar 38 28\ndiv 38 29\nprint 39\nprint 255")
- .replace("\n ", "\n");
- printProxy.setLength(0);
- if(!converted.startsWith("\n"))newCommands.append("print ");
- newCommands.append(converted).append("\n");
- }
- private void run()throws Exception{
- final long start=System.currentTimeMillis();
- for(;byteInd5000){
- System.out.println("Optimizer: \"Timeout!\"");
- throw new Exception("Code cannot be optimized, but compilation is a success!");
- }
- if(furthestLine>-1&&lines[furthestLine] memMap=new HashMap<>(){{
- put(' ', 0);
- put('A', 1);
- put('B', 2);
- put('C', 3);
- put('D', 4);
- put('E', 5);
- put('F', 6);
- put('G', 7);
- put('H', 8);
- put('I', 9);
- put('J', 10);
- put('K', 11);
- put('L', 12);
- put('M', 13);
- put('N', 14);
- put('O', 15);
- put('P', 16);
- put('Q', 17);
- put('R', 18);
- put('S', 19);
- put('T', 20);
- put('U', 21);
- put('V', 22);
- put('W', 23);
- put('X', 24);
- put('Y', 25);
- put('Z', 26);
- put('0', 27);
- put('1', 28);
- put('2', 29);
- put('3', 30);
- put('4', 31);
- put('5', 32);
- put('6', 33);
- put('7', 34);
- put('8', 35);
- put('9', 36);
- put('\n', 37);
- put('\u0000', 38);
- //hack-characters
- put('i', -255);
- put('-', -254);
- put('.', -253);
- }};
- private String convertToMemory(final String in){
- final StringBuilder output=new StringBuilder();
- for(final char c:in.toCharArray())output.append(memMap.get(c)).append(" ");
- return output.toString().trim();
- }
- int byteInd=0;
- final byte[] byteArr=new byte[1];
- private int next(final int len){
- try{
- if(len==8){
- byteInd++;
- for(long skipped=buffer.skip(byteInd-1);skipped255){
- System.arraycopy(temp, 0, mem, curInd, 255-curInd+1);
- memInd[ind]=255;
- return;
- }
- System.arraycopy(temp, 0, mem, curInd, temp.length);
- curInd+=temp.length;
- }else{
- final char[] tempty=rvar(ind);
- if(curInd+tempty.length-1>255){
- System.arraycopy(tempty, 0, mem, curInd, 255-curInd+1);
- memInd[ind]=255;
- return;
- }
- System.arraycopy(tempty, 0, mem, curInd, tempty.length);
- curInd+=tempty.length;
- }
- }
- memInd[memIndex]=curInd-1;
- return;
- }
- nvar(memIndex);
- final int memEndPoint=memIndex+chars.length-1;
- if(memEndPoint>255){
- System.arraycopy(chars, 0, mem, memIndex, 255-memIndex+1);
- memInd[memIndex]=255;
- return;
- }
- System.arraycopy(chars, 0, mem, memIndex, chars.length);
- memInd[memIndex]=memEndPoint;
- }
-
- private void nvar(final int ind){
- if(memInd[ind]==0)return;
- final char[] temp=new char[memInd[ind]-ind+1]; // To Avoid For-Loops.
- System.arraycopy(temp, 0, mem, ind, temp.length);
- memInd[ind]=0;
- }
-
- private void trim(){
- final int ind=next(8);
- final int max=next(8);
- if(max==0){
- nvar(ind);
- return;
- }
- if(max>memInd[ind]-ind)return;
- final char[] temp=rvar(ind);
- nvar(ind);
- System.arraycopy(temp, 0, mem, ind, max);
- memInd[ind]=ind+max-1;
- }
-
- private int findPeriod(final char[] arr){
- final int half=arr.length/2;
- for(int i=0;i9){
- aKnownNonNum[ind]=true;
- return new String(arr).hashCode();
- }
- result[0]+=num;
- result[0]*=10;
- final int i2=decimalInd+1+i;
- final int num2=arr[i2]-48;
- if(num2<0||num2>9){
- aKnownNonNum[ind]=true;
- return new String(arr).hashCode();
- }
- result[1]+=num2;
- result[1]/=10;
- }
- return (result[0]/10)+result[1];
- }else{ // BeCoz Long#parseLong() is slow and try-catch is expensive.
- double result=0;
- for(final char c:arr){
- final int num=c-48;
- if(num<0||num>9){
- aKnownNonNum[ind]=true;
- return new String(arr).hashCode();
- }
- result+=num;
- result*=10;
- }
- return result/10;
- }
- }
- private void math(final int op){
- final int ind1=next(8);
- final int ind2=next(8);
- final char[] str2=rvar(ind2);
- if(str2.length==0)return; // The earlier the call, the better.
- final char[] str1=rvar(ind1);
- if(str1.length<1&&str2.length>0){
- write(0, ind1, false, str2);
- return;
- }
- try{
- final double num1=toNum(str1, ind1);
- final double num2=toNum(str2, ind2);
- final double result=(op==0)?num1+num2:(op==1)?num1-num2:
- (op==2)?num1*num2:(op==3)?num1/num2:
- (op==4)?num1%num2:(int) (num1/num2);
- if(result!=result){ // Refer to Double#isNan(double v)
- nvar(ind1);
- mem[ind1]='i';
- memInd[ind1]=ind1;
- return;
- }
- if(result%1==0) write(0, ind1, false, Long.toString((long)result).toCharArray());
- else write(0, ind1, false, Double.toString(result).toCharArray());
- }catch(final Exception e){
- nvar(ind1);
- mem[ind1]='i';
- memInd[ind1]=ind1;
- }
- }
-
- final HashMap jumpBackFrequency=new HashMap();
- private boolean jump(final int op){ // Returns true if optimization should stop.
- final int ind1=next(8);
- final int ind2=next(8);
- final char[] arg1=rvar(ind1);
- final char[] arg2=rvar(ind2);
- final int com=next(16);
- if(
- (op==0&&toNum(arg1, ind1)>toNum(arg2, ind2))||
- (op==1&&toNum(arg1, ind1)size){
- byteInd=size;
- return;
- }
- for(;furthestLine++1){
- if(curByte<9)byteInd+=2;
- else if(curByte>9){
- if(curByte<14)byteInd+=4;
- else if(curByte==15)byteInd++;
- else byteInd+=next(8)+1;
- }
- }else if(curByte==1)byteInd++;
- else byteInd+=next(8)+1;
- }
- }
-
- private void print(){
- final int argCount=next(8);
- for(int i=0;i100)addToCommands();
- }
- }
-}
diff --git a/src/UFB/Runner.java b/src/UFB/Runner.java
index 8dba730..f2b8857 100644
--- a/src/UFB/Runner.java
+++ b/src/UFB/Runner.java
@@ -25,24 +25,46 @@
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.FileInputStream;
+import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
+import java.util.HashMap;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
class Runner{
final char[] mem=new char[256];
final int[] memInd=new int[256];
final boolean[] aKnownNonNum=new boolean[256];
+
final BufferedInputStream buffer;
+ final String fileName;
final int size;
final int[] lines;
int furthestLine=-1;
+
+ final boolean performance;
final boolean nanoseconds;
final boolean timeMethods;
final boolean backwardsCompat;
- public Runner(final String fileName, final boolean performance,
- final boolean nanoseconds, final boolean timeMethods,
- final boolean backwardsCompat)throws Exception{
+
+ public Runner(
+ final String fileName, final boolean performance,
+ final boolean nanoseconds, final boolean timeMethods,
+ final boolean backwardsCompat
+ )throws Exception{
+ final File f=new File(fileName);
+ if(!f.exists()){
+ System.out.println("File Provided Does Not Exist...\nTerminating...");
+ System.exit(1);
+ }
+ buffer=new BufferedInputStream(new FileInputStream(f));
+ buffer.mark(Integer.MAX_VALUE);
+ size=(int)f.length();
+ lines=new int[size];
mem[0]=' ';
aKnownNonNum[0]=true;
for(int i=0;i<26;i++){
@@ -53,83 +75,68 @@ public Runner(final String fileName, final boolean performance,
for(int i=0;i<10;i++)mem[i+27]=String.valueOf(i).charAt(0);
mem[37]='\n';
for(int i=37;i<256;i++)aKnownNonNum[i]=true;
+ this.fileName=fileName;
+ this.performance=performance;
this.nanoseconds=nanoseconds;
this.timeMethods=timeMethods;
this.backwardsCompat=backwardsCompat;
- if(fileName.length()!=0){
- final File f=new File(fileName);
- if(!f.exists()){
- System.out.println("File Provided Does Not Exist...\nTerminating...");
- System.exit(1);
- }
- buffer=new BufferedInputStream(new FileInputStream(f));
- buffer.mark(Integer.MAX_VALUE);
- size=(int)f.length();
- lines=new int[size];
- try{
- if(performance){
+ }
+
+ public void run()throws Exception{
+ final long runStart=(!nanoseconds)?System.currentTimeMillis():System.nanoTime();
+ try{
+ if(timeMethods){
+ for(;byteInd-1&&lines[furthestLine]-1&&lines[furthestLine]-1&&lines[furthestLine]-1&&lines[furthestLine]255){
System.arraycopy(temp, 0, mem, curInd, 255-curInd+1);
memInd[ind]=255;
+ final char[] converted=convertUnicode(new String(rvar(memIndex))).toCharArray();
+ System.arraycopy(converted, 0, mem, memIndex, converted.length);
+ memInd[memIndex]=memIndex+converted.length-1;
return;
}
System.arraycopy(temp, 0, mem, curInd, temp.length);
@@ -222,13 +232,19 @@ private void write(final int argCount, final int memIndex,
if(curInd+tempty.length-1>255){
System.arraycopy(tempty, 0, mem, curInd, 255-curInd+1);
memInd[ind]=255;
+ final char[] converted=convertUnicode(new String(rvar(memIndex))).toCharArray();
+ System.arraycopy(converted, 0, mem, memIndex, converted.length);
+ memInd[memIndex]=memIndex+converted.length-1;
return;
}
System.arraycopy(tempty, 0, mem, curInd, tempty.length);
curInd+=tempty.length;
}
}
- memInd[memIndex]=curInd-1;
+ memInd[memIndex]=curInd-1;
+ final char[] converted=convertUnicode(new String(rvar(memIndex))).toCharArray();
+ System.arraycopy(converted, 0, mem, memIndex, converted.length);
+ memInd[memIndex]=memIndex+converted.length-1;
return;
}
nvar(memIndex);
@@ -272,7 +288,7 @@ private int findPeriod(final char[] arr){
return -1;
}
private double toNum(final char[] arr, final int ind){
- if(aKnownNonNum[ind])return new String(arr).hashCode();
+ if(aKnownNonNum[ind])return hash(arr);
final int decimalInd=findPeriod(arr);
if(decimalInd!=-1){
final double[] result=new double[2];
@@ -280,7 +296,7 @@ private double toNum(final char[] arr, final int ind){
final int num=arr[i]-48;
if(num<0||num>9){
aKnownNonNum[ind]=true;
- return new String(arr).hashCode();
+ return hash(arr);
}
result[0]+=num;
result[0]*=10;
@@ -288,7 +304,7 @@ private double toNum(final char[] arr, final int ind){
final int num2=arr[i2]-48;
if(num2<0||num2>9){
aKnownNonNum[ind]=true;
- return new String(arr).hashCode();
+ return hash(arr);
}
result[1]+=num2;
result[1]/=10;
@@ -300,7 +316,8 @@ private double toNum(final char[] arr, final int ind){
final int num=c-48;
if(num<0||num>9){
aKnownNonNum[ind]=true;
- return new String(arr).hashCode();
+ return hash(arr);
+ // return new String(arr).hashCode();
}
result+=num;
result*=10;
@@ -308,6 +325,23 @@ private double toNum(final char[] arr, final int ind){
return result/10;
}
}
+ // A rip-off of String#hashCode();
+ // It just does too much, had to rewrite it.
+ private long hash(final char[] arr){
+ int hash=0;
+ for(int i=0;i9){
}
}
- final PrintWriter out=new PrintWriter(new BufferedWriter(
- new OutputStreamWriter(new FileOutputStream(FileDescriptor.out), "UTF-8"), 512
- ));
+ // TODO: Stop people from removing this; historically important.
+ // final PrintWriter out=new PrintWriter(new BufferedWriter(
+ // new OutputStreamWriter(new FileOutputStream(FileDescriptor.out), "UTF-8"), 512
+ // ));
+ // private void print(){
+ // final int argCount=next(8);
+ // for(int i=0;i");
write(0, ind, false, scan.readLine().toCharArray());
}
-}
+
+ public void runOptimized()throws Exception{
+ scan.close();
+ try{
+ scan.close();
+ final long start=System.currentTimeMillis();
+ for(;byteInd5000){
+ System.out.println("Optimizer: \"Timeout!\"");
+ throw new Exception("Code cannot be optimized, but compilation is a success!");
+ }
+ if(furthestLine>-1&&lines[furthestLine] memMap=new HashMap<>(){{
+ put(' ', 0); put('A', 1); put('B', 2); put('C', 3); put('D', 4);
+ put('E', 5); put('F', 6); put('G', 7); put('H', 8); put('I', 9);
+ put('J', 10); put('K', 11); put('L', 12); put('M', 13); put('N', 14);
+ put('O', 15); put('P', 16); put('Q', 17); put('R', 18); put('S', 19);
+ put('T', 20); put('U', 21); put('V', 22); put('W', 23); put('X', 24);
+ put('Y', 25); put('Z', 26);
+ put('0', 27); put('1', 28); put('2', 29); put('3', 30); put('4', 31);
+ put('5', 32); put('6', 33); put('7', 34); put('8', 35); put('9', 36);
+ put('\n', 37);
+ put('\u0000', 38);
+ //hack-characters
+ put('i', -255); put('-', -254); put('.', -253);
+ }};
+
+ final HashMap jumpBackFrequency=new HashMap();
+ private boolean jumpOptimizer(final int op){ // Returns true if optimization should stop.
+ final int ind1=next(8);
+ final int ind2=next(8);
+ final char[] arg1=rvar(ind1);
+ final char[] arg2=rvar(ind2);
+ final int com=next(16);
+ if(
+ (op==0&&toNum(arg1, ind1)>toNum(arg2, ind2))||
+ (op==1&&toNum(arg1, ind1)249){
+ final int length=printProxy.length()-printProxy.toString().lastIndexOf("U");
+ if(length<5)
+ untilDump=5-length;
+ else
+ addToCommands();
+ }
+ final int argCount=next(8);
+ for(int i=0;i254)addToCommands();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/UFB/UFB.java b/src/UFB/UFB.java
index 5cf808b..6f24ef2 100644
--- a/src/UFB/UFB.java
+++ b/src/UFB/UFB.java
@@ -19,22 +19,21 @@
**/
class UFB{
- //----------------------------------------------------------------------//
- /**TODO: ALWAYS CHANGE VERSION TAG.
- * DO NOT Change '1' in "1.*.*".
- * MINOR CHANGES should go in "1.MINOR.*".
- * PATCH CHANGES should go in "1.*.PATCH".
- * MINOR CHANGES should give new commands/major features.
- * PATCH CHANGES should give new flags/performance-boosts/bug-fixes/etc.
- **/
- final static String version_tag="v1.3.0";
- //----------------------------------------------------------------------//
public static void main(final String[]a)throws Exception{
final FlagManager flagManager=new FlagManager(a);
if(flagManager.isFlagActivated('v')){
+ //----------------------------------------------------------------------//
+ /**TODO: ALWAYS CHANGE SEMANTIC VERSION BEFORE RELEASING.
+ * DO NOT Change '1' in "1.*.*".
+ * MINOR CHANGES should go in "1.MINOR.*".
+ * PATCH CHANGES should go in "1.*.PATCH".
+ * MINOR CHANGES should give new commands/major features.
+ * PATCH CHANGES should give new flags/performance-boosts/bug-fixes/etc.
+ **/
+ //----------------------------------------------------------------------//
System.out.printf(
"UFB version: %s (master)\n%s\n\n",
- version_tag,
+ "v1.4.0",
"Flag triggered, continuing anyway..."
);
}
@@ -87,16 +86,22 @@ public static void main(final String[]a)throws Exception{
}
if(flagManager.isFlagActivated('c')){
if(fileName.endsWith(".ufbb")){
- System.out.println("Could not compile an already compiled source code.");
- System.out.println("Remove the compilation flag to run the compiled program.");
+ System.out.printf(
+ "%s\n%s\n",
+ "Could not compile an already compiled source code.",
+ "Remove the compilation flag to run the compiled program."
+ );
return;
}
- new UFBC(fileName);
+ new UFBC().compile(fileName, !flagManager.isLongFlagActivated("unoptimized"));
return;
}
if(fileName.endsWith(".ufb")){
- System.out.println("Could not run uncompiled source code.");
- System.out.println("Add the compilation flag to compile the program.");
+ System.out.printf(
+ "%s\n%s\n",
+ "Could not run uncompiled source code.",
+ "Add the compilation flag to compile the program."
+ );
return;
}
new Runner(
@@ -105,6 +110,6 @@ public static void main(final String[]a)throws Exception{
flagManager.isFlagActivated('n'),
flagManager.isFlagActivated('m'),
flagManager.isFlagActivated('b')
- );
+ ).run();
}
}
\ No newline at end of file
diff --git a/src/UFB/UFBC.java b/src/UFB/UFBC.java
index ae63877..ebfb5b6 100644
--- a/src/UFB/UFBC.java
+++ b/src/UFB/UFBC.java
@@ -26,7 +26,7 @@
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
-
+import java.util.regex.Matcher;
import java.util.regex.Pattern;
class UFBC{
@@ -40,153 +40,210 @@ class UFBC{
* 12 - 1100 - je | 13 - 1101 - jne
* 14 - 1110 - print | 15 - 1111 - read
**/
- final static Pattern allowed=Pattern.compile("[^a-zA-Z0-9 \n-|,\t]");
- final static Pattern divider=Pattern.compile("[-|, \t]+");
- final static Pattern empties=Pattern.compile(" *\n+ *");
- final static Pattern comment=Pattern.compile("//.*\n*");
- final static Pattern morecom=Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL);
- final static StringBuilder errors=new StringBuilder();
- public UFBC(final String fileName)throws Exception{
- compile(fileName, true);
- }
- public static void compile(final String fileName, final boolean recompile)throws Exception{
+ final Pattern divider=Pattern.compile("[-|, \t]+");
+ final Pattern empties=Pattern.compile(" *\n+ *");
+ final Pattern comment=Pattern.compile("//.*\n*");
+ final Pattern morecom=Pattern.compile("/\\*.*?\\*/", Pattern.DOTALL);
+ final StringBuilder errors=new StringBuilder();
+ public UFBC(){}
+ public void compile(final String fileName, final boolean recompile)throws Exception{
final StringBuilder inBuilder=new StringBuilder();
try(final BufferedReader scan=new BufferedReader(new FileReader(fileName))){
String temp;
while((temp=scan.readLine())!=null)inBuilder.append(temp).append("\n");
}
- final String input=inBuilder.toString();
- final String[] arr=empties.split(
+ String input=inBuilder.toString();
+ final Pattern dividerInString=Pattern.compile("\".*([-|, \t]).*\"");
+ try{
+ for(final Matcher m=dividerInString.matcher(input);m.find();)
+ for(final Matcher m2=divider.matcher(input);m2.find(m.start());){
+ input=new StringBuilder(input.substring(0, m2.start()))
+ .append("UU")
+ .append(manPadding(Integer.toString(m2.group().charAt(0)+0), 4))
+ .append(input.substring(m2.start()+1)).toString();
+ m.reset(input).find();
+ m2.reset(input);
+ }
+ }catch(final Exception e){}
+ final String[] arr=empties.split(
divider.matcher(
- allowed.matcher(
- comment.matcher(
- morecom.matcher(
- input.toLowerCase()
- ).replaceAll("\n")
- ).replaceAll("\n")
- ).replaceAll("")
+ comment.matcher(
+ morecom.matcher(
+ input
+ ).replaceAll("\n")
+ ).replaceAll("\n")
).replaceAll(" ")
);
final StringBuilder warnings=new StringBuilder();
final ArrayList list=new ArrayList<>();
+ final Pattern jumps=Pattern.compile("j(m|l|e|ne)", Pattern.CASE_INSENSITIVE);
+ final Pattern maths=Pattern.compile("add|sub|mul|div|r*mod", Pattern.CASE_INSENSITIVE);
+ final Pattern pwvar=Pattern.compile("wvar|print", Pattern.CASE_INSENSITIVE);
boolean cancelOptimization=false;
for(final String arrTemp:arr){
- final String[] temp=divider.split(arrTemp);
- if(temp.length<2&&temp.length>0&&!temp[0].equals("nop"))
- warnings.append("Warning: |\n")
- .append(" Command: |\n")
- .append(" \"")
- .append(temp[0])
- .append("\" Will Be Ignored For It Has No Arguments: |\n")
- .append(" ")
- .append(lineGen(temp));
- else{
+ final String[] realTemp=divider.split(arrTemp);
+ final ArrayList tempList=new ArrayList<>();
+ for(String s:realTemp){
+ if(s.startsWith("\"")&&s.endsWith("\""))
+ for(final String s2:convertToMem(s.substring(1, s.length()-1)))
+ tempList.add(s2);
+ else
+ tempList.add(s);
+ }
+ final String[] temp=tempList.toArray(new String[tempList.size()]);
+ if(temp.length<2&&temp.length>0&&!temp[0].equalsIgnoreCase("nop")){
+ if(!(temp[0].equals("\n")||temp[0].trim().isEmpty()))
+ warnings.append("Warning: |\n")
+ .append(" Command: |\n")
+ .append(" \"")
+ .append(temp[0])
+ .append("\" Will Be Ignored For It Has No Arguments: |\n")
+ .append(" ")
+ .append(lineGen(temp));
+ }else{
boolean isCommand=true;
- switch(temp[0]){
- case "trim":
- checkLength(temp, 3);
- break;
- case "nvar":
- if(checkLength(temp, 2))break;
- checkIfMemSafe(temp, temp[1]);
- break;
- case "read":
- if(checkLength(temp, 2))break;
- checkIfMemSafe(temp, temp[1]);
- cancelOptimization=true;
- break;
- case "jm":
- case "jl":
- case "je":
- case "jne":
- if(checkLength(temp, 4))break;
- case "add":
- case "sub":
- case "mul":
- case "div":
- case "mod":
- case "rmod":
- if(!temp[0].startsWith("j")){
- if(checkLength(temp, 3))break;
- checkIfMemSafe(temp, temp[1]);
- }
- for(byte i=1;i<3;i++)checkIfMem(temp, temp[i]);
- break;
- case "wvar":
- case "print":
- if(temp.length>Byte.MAX_VALUE-1){
- error(
- temp, "Command", temp[0],
- "Has Too Many Arguments"
- );
- break;
- }
- if(temp[0].startsWith("w"))checkIfMemSafe(temp, temp[1]);
- for(byte i=2;i256)
+ error(
+ realTemp, "Command", temp[0],
+ "Has Too Many Arguments",
+ lineGen(temp)
+ );
+ else{
+ if(temp[0].startsWith("w"))
+ checkIfMemSafe(temp, temp[1]);
+ for(short i=2;i mems=new ArrayList<>();
+ boolean backSlash=false;
+ for(final char c:in.toCharArray()){
+ if(memMap.containsKey(c))
+ mems.add(memMap.get(c).toString());
+ else{
+ if(c=='\\'){
+ if(backSlash){
+ backSlash=false;
+ mems.add("21");
+ mems.add("21");
+ for(final char c2:manPadding(Integer.toString('\\'), 4).toCharArray())
+ mems.add(memMap.get(c2).toString());
+ }else{
+ backSlash=true;
+ }
+ }else if(backSlash){
+ if(c=='n'){
+ mems.add("37");
+ }else{
+ mems.add("21");
+ mems.add("21");
+ for(final char c2:manPadding(Integer.toString((int)c), 4).toCharArray())
+ mems.add(memMap.get(c2).toString());
+ }
+ backSlash=false;
+ }else{
+ mems.add("21");
+ mems.add("21");
+ for(final char c2:manPadding(Integer.toString((int)c), 4).toCharArray())
+ mems.add(memMap.get(c2).toString());
+ }
+ }
+ }
+ return mems.toArray(new String[mems.size()]);
+ }
+ final HashMap memMap=new HashMap<>(){{
+ put(' ', 0); put('A', 1); put('B', 2); put('C', 3); put('D', 4);
+ put('E', 5); put('F', 6); put('G', 7); put('H', 8); put('I', 9);
+ put('J', 10); put('K', 11); put('L', 12); put('M', 13); put('N', 14);
+ put('O', 15); put('P', 16); put('Q', 17); put('R', 18); put('S', 19);
+ put('T', 20); put('U', 21); put('V', 22); put('W', 23); put('X', 24);
+ put('Y', 25); put('Z', 26);
+ put('0', 27); put('1', 28); put('2', 29); put('3', 30); put('4', 31);
+ put('5', 32); put('6', 33); put('7', 34); put('8', 35); put('9', 36);
+ put('\n', 37);
+ }};
+ private void writeToFile(final String outName, final ArrayList list)throws Exception{
+ final File outFile=new File(outName);
+ outFile.createNewFile();
+ try(final FileOutputStream stream=new FileOutputStream(outFile)){
+ for(int i=0;i255)
error(
@@ -200,7 +257,7 @@ private static void checkIfMem(final String[] temp, final String s){
);
}
}
- private static void checkIfMemSafe(final String[] temp, final String s){
+ private void checkIfMemSafe(final String[] temp, final String s){
try{
if(Long.parseLong(s)<38)
error(
@@ -215,7 +272,7 @@ private static void checkIfMemSafe(final String[] temp, final String s){
}
}
// false if error is not thrown. Misleading eh?
- private static boolean checkLength(final String[] temp, final int length){
+ private boolean checkLength(final String[] temp, final int length){
if(temp.length!=length){
final String num=(length<1)?"Zero":(length==1)?"One":(length==2)?"Two":"Three";
error(
@@ -226,40 +283,66 @@ private static boolean checkLength(final String[] temp, final int length){
}
return false;
}
- private static String lineGen(final String[]temp){
+ private String lineGen(final String[]temp){
return Arrays.toString(temp).substring(1).replace(", ", " ").replace("]", "\n\n");
}
- private static void error(final String[] temp, final String... in){
- errors.append("Error: |\n")
- .append(String.format(" %s: |\n", in[0]))
- .append(String.format(" \"%s\" %s: |\n", in[1], in[2]))
- .append(String.format(" %s", lineGen(temp)));
+ private void error(final String[] temp, final String... in){
+ if(in.length<4)
+ errors.append("Error: |\n")
+ .append(String.format(" %s: |\n", in[0]))
+ .append(String.format(" \"%s\" %s: |\n", in[1], in[2]))
+ .append(String.format(" %s", lineGen(temp)));
+ else
+ errors.append("Error: |\n")
+ .append(String.format(" %s: |\n", in[0]))
+ .append(String.format(" \"%s\" %s: |\n", in[1], in[2]))
+ .append(String.format(" %s", convertUnicode(lineGen(temp).replace("\n\n", "\n"))))
+ .append(String.format(" %s: |\n", "Which Is When Converted"))
+ .append(String.format(" %s", in[3]));
}
- private static String manPadding(final String str, final int i){
- final StringBuilder reverse=new StringBuilder(str).reverse();
- while(reverse.length()i)reverse.delete(0, 1);
- return reverse.reverse().toString();
+ private long toLongAbsolute(final char[] arr){
+ // BeCoz Long#parseLong() is slow and try-catch is expensive.
+ long result=0;
+ for(final char c:arr){
+ result+=c-48;
+ result*=10;
+ }
+ return result/10;
+ }
+ final Pattern unicode=Pattern.compile("(uu|UU)(\\d{1,4})");
+ private String convertUnicode(final String in){
+ if(in.length()<2)return in;
+ String temp=in;
+ try{
+ for(final Matcher m=unicode.matcher(temp);m.find();m.reset(temp)){
+ temp=new StringBuilder(temp.substring(0, m.start()))
+ .append((char)toLongAbsolute(
+ temp.substring(m.start()+2, m.end()).toCharArray()
+ ))
+ .append(temp.substring(m.end())).toString();
+ }
+ }catch(final Exception e){}
+ return temp;
+ }
+ public static String manPadding(final String str, final int i){
+ return String.format(
+ new StringBuilder("%").append(i).append("s").toString(),
+ str
+ ).replace(" ", "0");
}
- final static HashMap binaryMap=new HashMap<>(){{
- put("wvar" , 0 );
- put("nvar" , 1 );
- put("trim" , 2 );
- put("add" , 3 );
- put("sub" , 4 );
- put("mul" , 5 );
- put("div" , 6 );
- put("mod" , 7 );
- put("rmod" , 8 );
- put("nop" , 9 );
- put("jm" , 10);
- put("jl" , 11);
- put("je" , 12);
- put("jne" , 13);
- put("print", 14);
- put("read" , 15);
+ final HashMap binaryMap=new HashMap<>(){{
+ final String[] commands={
+ "wvar", "nvar", "trim",
+ "add", "sub", "mul", "div", "mod", "rmod",
+ "nop",
+ "jm", "jl", "je", "jne",
+ "print", "read"
+ };
+ for(short i=0;i