package oop;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
public class vTableClass {
String classname;
String modifier;
LinkedList<String> namespace;
HashSet<String> includes;
HashSet<String> usings;
HashSet<String> overloadedmethods;
vTableClass superclass;
LinkedList<vTableMethodLayoutLine> vMethodLayout;
LinkedList<vTableLayoutLine> vTableLayout;
LinkedList<vTableAddressLine> vTableAddress;
LinkedList<vClassConstructor> vClassConstructors;
vTableForwardDeclarations forwarddeclarations;
//LinkedList<String> dataLayout;
LinkedList<vTableData> dataLayout;
File file;
//create a new linked list of vClassConstructors
vTableMethodLayoutLine currentmethod;
vTableLayoutLine currentlayout;
vTableAddressLine currentaddress;
vClassConstructor currentconstructor;
boolean writeable;
public vTableClass(String classnamable){
writeable = true;
classname = classnamable;
superclass = null;
//struct = "struct " + "__" + struct;
vMethodLayout = new LinkedList<vTableMethodLayoutLine>();
vTableLayout = new LinkedList<vTableLayoutLine>();
vTableAddress = new LinkedList<vTableAddressLine>();
vClassConstructors = new LinkedList<vClassConstructor>();
forwarddeclarations = new vTableForwardDeclarations();
namespace = new LinkedList<String>();
dataLayout = new LinkedList<vTableData>();
overloadedmethods = new HashSet<String>();
includes = new HashSet<String>();
usings = new HashSet<String>();
}
public void setFile(File writeto){
file = writeto;
//System.out.println("file set to " + file.getName());
}
public void setNoWrite(){
writeable = false;
}
public void setModifier(String mod){
modifier = mod;
}
public void addUsings(String state){
//System.out.println("added using " + state);
usings.add(state);
}
public void addSuperClass(vTableClass parenting){
//System.out.println("adding superclass " + parenting.classname);
superclass = parenting;
copysupertable();
}
public void addForwardDeclaration(String currentclass){
forwarddeclarations.addForwardDeclaration(currentclass);
forwarddeclarations.addForwardVTable(currentclass);
forwarddeclarations.addTypeDeclarations(currentclass);
}
public void addIncludes(String s){
if(!includes.contains(s) && !s.equals("\"" + classname + ".h\"")){
System.out.println("added includes " + s);
includes.add(s);
}
}
public boolean checkJavaLang(String s){
//System.out.println("checking " + s);
if(s.equals("String") || s.equals("Object") || s.equals("Class") || s.equals("Exception")){
return true;
}
return false;
}
public void addAdditionalForwards(String s){
if(!this.checkJavaLang(s)){
if(!forwarddeclarations.hasDeclarations(s)){
forwarddeclarations.addForwardDeclaration(s);
forwarddeclarations.addTypeDeclarations(s);
}
}
// if(!includes.contains("\"" + s + ".h\"") && (checkJavaLang(s) != true) && !s.equals(classname)){
// includes.add("\"" + s + ".h\"");
// addUsings(s);
// }
}
public void copysuperdatalayout(){
Iterator<vTableData> superdata = superclass.dataLayout.iterator();
while(superdata.hasNext()){
vTableData datable = superdata.next();
Iterator<vTableData> currentdata = dataLayout.iterator();
boolean namecheck = false;
while(currentdata.hasNext()){
vTableData currentdatas = currentdata.next();
if(datable.name.equals(currentdatas.name)){
namecheck = true;
}
}
if(namecheck == false && !datable.modifiers.contains("static")){
dataLayout.add(datable);
}
}
}
public void copysupertable(){
Iterator<vTableMethodLayoutLine> methoditerate = superclass.vMethodLayout.iterator();
//Iterator<vTableAddressLine> addressiterate = superclass.vTableAddress.iterator();
//Iterator<vTableLayoutLine> layoutiterate = superclass.vTableLayout.iterator();
Iterator<String> superincludes = superclass.includes.iterator();
while(superincludes.hasNext()){
String nexts = superincludes.next();
if(!nexts.equals("\"" + classname + ".h\""))
includes.add(nexts);
}
if(superclass.classname.equals("Object")){
includes.add("\"java_lang.h" + "\"");
}
else{
includes.add("\"" + superclass.classname + ".h" + "\"");
}
//add in __isa
vTableLayout.add(superclass.vTableLayout.getFirst());
vTableAddress.add(superclass.vTableAddress.getFirst());
while(methoditerate.hasNext()){
currentmethod = methoditerate.next();
//if(layoutiterate.hasNext()){
//currentlayout = layoutiterate.next();
//currentmethod.matchinglayout.setReferenceType(classname);
//currentaddress = addressiterate.next();
if(currentmethod.methodname.equals("__delete")){
//currentaddress.setClassName(classname);
//System.out.println("copying specialmethod " + currentaddress.methodname);
//currentlayout.setReferenceType(this.classname);
//currentmethod.setReferenceType("__" + classname + "*");
//currentlayout.setReferenceType("__" + classname + "*");
vMethodLayout.add(currentmethod);
vTableLayout.add(currentmethod.matchinglayout);
vTableAddress.add(currentmethod.matchingaddress);
// vTableLayout.add(currentlayout);
// vTableAddress.add(currentaddress);
}
else if((currentmethod.visibility.equals("public") || currentmethod.visibility.equals("protected")) && currentmethod.staticcheck != true){
//System.out.println("copying supermethod " + superclass.classname + currentmethod.methodname);
//currentmethod.setReferenceType(classname);
//currentaddress.setTypeCast(currentmethod.returntype,currentmethod.parameters);
vMethodLayout.add(currentmethod);
if(currentmethod.overloaded == true){
overloadedmethods.add(currentmethod.methodname);
}
if(currentmethod.matchingaddress != null){
vTableLayout.add(currentmethod.matchinglayout);
vTableAddress.add(currentmethod.matchingaddress);
}
}
}
// else{
// if((currentmethod.visibility.equals("public") || currentmethod.visibility.equals("protected")) && currentmethod.staticcheck != true){
// //System.out.println("copying supermethod " + superclass.classname + currentmethod.methodname);
// currentmethod.setReferenceType(classname);
// //currentaddress.setTypeCast(currentmethod.returntype,currentmethod.parameters);
// //vTableLayout.add(currentlayout);
// //vTableAddress.add(currentaddress);
// vMethodLayout.add(currentmethod);
// }
// }
}
public void addNameSpace(String s){
namespace.add(s);
}
public void addDataLayout(vTableData s){
dataLayout.add(s);
}
public void newConstructor(){
currentconstructor = new vClassConstructor(this);
}
public void appendConstructor(String s){
currentconstructor.addParameter(s);
}
public void addConstructor(){
vClassConstructors.add(currentconstructor);
}
public boolean checkOverride(){
int index = 0;
boolean override = false;
try{
//note that eventually the while loop will run into an index out of bounds error
//but the exception will be caught in the try catch loop, effectively breaking from the loop
//whether an override or not an override
while(true){
vTableMethodLayoutLine scanline = vMethodLayout.get(index);
if(scanline.methodname.equals(currentmethod.methodname) && scanline.parameters.equals(currentmethod.parameters)){
if(scanline.finalcheck == true){
throw new Exception(currentmethod.methodname + ":Invalid Override, Super Method is final");
}
else{
scanline.matchingaddress.setOverride(classname);
override = true;
break;
}
}
index++;
}
}
catch(Exception e){
//e.printStackTrace();
//nothing doin, intentional exception for when an index out of bounds error occurs (meaning no override found)
}
return override;
}
public void checkOverload(){
int index = 0;
boolean overload = false;
try{
//note that eventually the while loop will run into an index out of bounds error
//but the exception will be caught in the try catch loop, effectively breaking from the loop
//whether an override or not an override
while(true){
vTableMethodLayoutLine scanline = vMethodLayout.get(index);
if(scanline.methodname.equals(currentmethod.methodname)){
scanline.setOverload();
if(!scanline.parent.equals(this.superclass)){
superclass.addOverload(scanline.methodname);
}
superclass.addOverload(currentmethod.methodname);
currentmethod.setOverload();
currentlayout.setOverload();
currentaddress.setOverload();
//scanline.matchingaddress.setOverride(classname);
overloadedmethods.add(currentmethod.methodname);
overload = true;
break;
}
index++;
}
}
catch(Exception e){
//nothing doin, intentional exception for when an index out of bounds error occurs (meaning no override found)
}
}
public void addOverload(String name){
overloadedmethods.add(name);
}
public void resolveOverloads(){
//this method is called right before printing to resolve overloaded methods and the other objects
//needed to be edited because of them
Iterator iterate = vMethodLayout.iterator();
while(iterate.hasNext()){
vTableMethodLayoutLine current = (vTableMethodLayoutLine)iterate.next();
if(overloadedmethods.contains(current.methodname)){
current.setOverload(); //this setOverload method cascades to the matching tablelayout and address lines
}
}
// iterate = vTableLayout.iterator();
// while(iterate.hasNext()){
// vTableLayoutLine current = (vTableLayoutLine)iterate.next();
// if(current.matchingmethod.overloaded == true || overloadedmethods.contains(current.methodname)){
// current.setOverload();
// }
// }
}
//Create a new vTableMethodLayoutLine
public void newMethodLayout(){
currentmethod = new vTableMethodLayoutLine(this);
}
//note that by the time this method is called, all of the related method
//entries will have been assembled as well so they are finalized in terms of visitors
//includes currentaddress, currentmethod, and currentlayout
public void addMethod(){
setMatching();
boolean overridecheck = checkOverride();
if(overridecheck == false){
checkOverload();
vMethodLayout.add(currentmethod);
}
}
public boolean checkStaticPrivate(){
//System.out.println("checking static private of " + currentmethod.methodname);
//System.out.println(currentmethod.methodname + " is " + currentmethod.modifier);
if(currentmethod.staticcheck == true || currentmethod.visibility.contains("private")){
return true;
}
else{
return false;
}
}
public void setMatching(){
if(currentlayout != null && currentmethod != null && currentaddress != null){
currentmethod.setMatching(currentlayout, currentaddress);
currentaddress.setMatching(currentlayout, currentmethod);
currentlayout.setMatching(currentaddress, currentmethod);
}
}
public void appendMethod(String command, String arg){
if(command.equals("ReferenceType")){
currentmethod.setReferenceType(arg);
}
else if(command.equals("Modifier")){
//System.out.println("method for " + currentmethod.methodname + " set to " + arg);
currentmethod.setModifer(arg);
//currentmethod.setVisiblity(arg);
}
else if(command.equals("ReturnType")){
currentmethod.setReturnType(arg);
}
else if(command.equals("MethodName")){
currentmethod.setMethodName(arg);
}
else if(command.equals("Parameters")){
currentmethod.setParameters(arg);
}
else if(command.equals("ObjectVisiblity")){
currentmethod.setVisiblity(arg);
}
else{
System.out.println("Invalid command " + command);
}
}
//Create a new vTableLayoutLine
public void newTableLayout(){
currentlayout = new vTableLayoutLine(this);
}
public void addTableLayout(){
boolean check = checkOverride();
if(check == false){
vTableLayout.add(currentlayout);
}
}
//note to self, declare the createline method in vtablemethodlayoutline obsolete and move the functionality
//to the printline method instead
public void appendTableLayout(String command, String arg){
if(command.equals("ReferenceType")){
currentlayout.setReferenceType(arg);
}
else if(command.equals("ReturnType")){
currentlayout.setReturnType(arg);
}
else if(command.equals("MethodName")){
currentlayout.setMethodName(arg);
}
else if(command.equals("Parameters")){
currentlayout.setParameters(arg);
}
else{
System.out.println("Invalid command " + command);
}
}
//Create a new vTableAddressLine
public void newTableAddress(){
currentaddress = new vTableAddressLine(this);
}
public void addTableAddress(){
//checkOverride("Address");
boolean check = checkOverride();
if(check == false){
vTableAddress.add(currentaddress);
}
}
//note to self, make the createline method in vtableaddressline obsolete, move the functionality
//to the printline method instead
public void appendAddress(String command, String arg){
if(command.equals("TypeCast")){
//currentaddress.setTypeCast(arg);
}
else if(command.equals("ClassName")){
currentaddress.setClassName(arg);
}
else if(command.equals("MethodName")){
currentaddress.setMethodName(arg);
}
else{
System.out.println("Invalid commawriternd " + command);
}
}
public void writeFile(BufferedWriter writer, HashMap usingStates){
try {
//FileWriter writee = new FileWriter(file);
//BufferedWriter writer = new BufferedWriter(writee);
Iterator<String> iterate = includes.iterator();
writer.write("#pragma once \r\r");
while(iterate.hasNext()){
writer.write("#include " + iterate.next() + "\r");
}
writer.write("\r");
iterate = namespace.iterator();
while(iterate.hasNext()){
writer.write("namespace " + iterate.next() + "{\r");
}
forwarddeclarations.writefile(writer);
//using statements
writer.write("using namespace java::lang;\r"); //always by default
//other statements
iterate = usings.iterator();
HashSet<String> writtenUsings = new HashSet<String>();
while(iterate.hasNext()){
String s = (String)usingStates.get(iterate.next());
if(!writtenUsings.contains(s)){
writer.write( s + ";\r");
writtenUsings.add(s);
}
}
writer.write("\r");
writer.write("struct " + "__" + classname + "{ \r");
writer.write("__" + classname + "_VT*" + " __vptr;\r");
Iterator<vTableData> datas = dataLayout.iterator();
while(datas.hasNext()){
vTableData currentdata = datas.next();
writer.write(currentdata.getDataString());
}
writer.write("\r");
//writer.flush();
//writer.close();
//the constructors
//writer.write("__" + classname + "();\r\r"); the basic constructor, no arguments
if(vClassConstructors.isEmpty()){
vClassConstructor noargs = new vClassConstructor(this);
vClassConstructors.add(noargs);
}
Iterator<vClassConstructor> constructorIterate = vClassConstructors.iterator();
boolean noargcheck = false;
while(constructorIterate.hasNext()){
vClassConstructor constructor = constructorIterate.next();
if(constructor.parameters == null){
noargcheck = true;
}
constructor.writeFile(writer);
}
if(noargcheck == false){
vClassConstructor noargs = new vClassConstructor(this);
noargs.writeFile(writer);
}
Iterator<vTableMethodLayoutLine> methodIterate = vMethodLayout.iterator();
while(methodIterate.hasNext()){
vTableMethodLayoutLine current = methodIterate.next();
current.writeFile(writer, this);
}
//writer = new BufferedWriter(writee);
writer.write("\r");
writer.write("static Class __class(); \r\r");
writer.write("static " + "__" + classname +"_VT __vtable;\r");
writer.write("};\r\r");
writer.write("struct __" + classname + "_VT { \r");
//writer.close();
Iterator<vTableLayoutLine> tableIterate = vTableLayout.iterator();
while(tableIterate.hasNext()){
vTableLayoutLine current = tableIterate.next();
if(current!=null){
current.writeFile(writer, this);
}
}
//writer = new BufferedWriter(writee);
writer.write("\r");
writer.write("__" + classname + "_VT()\r: ");
//writer.close();
Iterator<vTableAddressLine> addressIterate = vTableAddress.iterator();
while(addressIterate.hasNext()){
vTableAddressLine current = addressIterate.next();
if(current!=null)
current.writeFile(writer, this);
}
//writer = new BufferedWriter(writee);
writer.write("{}\r};\r");
//writer.close();
iterate = namespace.iterator();
while(iterate.hasNext()){
iterate.next();
writer.write("}\r");
}
//writer = new BufferedWriter(writee);
writer.write("\r");
writer.flush();
//writer.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//outdated console printer
public void printLines(){
Iterator<String> iterate = namespace.iterator();
while(iterate.hasNext()){
System.out.print("namespace " + iterate.next() + "{\r");
}
System.out.print("struct " + "__" + classname + "{ \r");
System.out.print("__" + classname + "_VT*" + " __vptr;\r");
while(!dataLayout.isEmpty()){
System.out.print(dataLayout.pop());
}
System.out.print("\r");
//the constructors
//System.out.print("__" + classname + "();\r\r"); the basic constructor, no arguments
while(!vClassConstructors.isEmpty()){
vClassConstructor constructor = vClassConstructors.pop();
constructor.printLine();
}
while(!vMethodLayout.isEmpty()){
vTableMethodLayoutLine current = vMethodLayout.pop();
current.printLine();
}
System.out.print("\r");
System.out.print("static Class __class(); \r\r");
System.out.print("static " + "__" + classname +"_VT _vtable;\r");
System.out.print("};\r\r");
System.out.print("struct __" + classname + "_VT { \r");
while(!vTableLayout.isEmpty()){
vTableLayoutLine current = vTableLayout.pop();
current.printLine();
}
System.out.print("\r");
System.out.print("__" + classname + "_VT()\r: ");
while(!vTableAddress.isEmpty()){
vTableAddressLine current = vTableAddress.pop();
current.printLine();
}
System.out.print("{}\r};\r");
iterate = namespace.iterator();
while(iterate.hasNext()){
iterate.next();
System.out.print("}\r");
}
System.out.print("\r");
}
}