From 6bde630d5d61aef9f54f7378515d40d9985062f5 Mon Sep 17 00:00:00 2001 From: jzhou <jzhou> Date: Mon, 25 Oct 2010 22:49:57 +0000 Subject: [PATCH] Hack the compiler to support 'abstract' keyword for mgc version. Abstract classes/methods can be compiled but fully semantic check is not supported. Now we generate an empty method for each declared abstract method and do not check if the subclasses have implemented their inheried abstract methods. --- Robust/src/IR/ClassDescriptor.java | 4 ++ Robust/src/IR/MethodDescriptor.java | 4 ++ Robust/src/IR/Tree/BuildIR.java | 2 + Robust/src/IR/Tree/Modifiers.java | 8 ++- Robust/src/IR/Tree/SemanticCheck.java | 9 +++ Robust/src/Parse/java14.cup | 2 +- Robust/src/Tests/AbstractTest.java | 88 +++++++++++++++++++++++++++ 7 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 Robust/src/Tests/AbstractTest.java diff --git a/Robust/src/IR/ClassDescriptor.java b/Robust/src/IR/ClassDescriptor.java index b7862990..f9d19595 100644 --- a/Robust/src/IR/ClassDescriptor.java +++ b/Robust/src/IR/ClassDescriptor.java @@ -168,4 +168,8 @@ public class ClassDescriptor extends Descriptor { public int getNumStaticFields() { return this.numstaticfields; } + + public boolean isAbstract() { + return this.modifiers.isAbstract(); + } } diff --git a/Robust/src/IR/MethodDescriptor.java b/Robust/src/IR/MethodDescriptor.java index cda2616d..beaee6be 100644 --- a/Robust/src/IR/MethodDescriptor.java +++ b/Robust/src/IR/MethodDescriptor.java @@ -121,6 +121,10 @@ public class MethodDescriptor extends Descriptor { public boolean isStatic() { return modifier.isStatic(); } + + public boolean isAbstract() { + return modifier.isAbstract(); + } public boolean isConstructor() { return (returntype==null); diff --git a/Robust/src/IR/Tree/BuildIR.java b/Robust/src/IR/Tree/BuildIR.java index e5f888ea..5cef8cc2 100644 --- a/Robust/src/IR/Tree/BuildIR.java +++ b/Robust/src/IR/Tree/BuildIR.java @@ -920,6 +920,8 @@ public class BuildIR { m.addModifier(Modifiers.SYNCHRONIZED); else if (isNode(modn,"atomic")) m.addModifier(Modifiers.ATOMIC); + else if (isNode(modn,"abstract")) + m.addModifier(Modifiers.ABSTRACT); else throw new Error("Unrecognized Modifier"); } } diff --git a/Robust/src/IR/Tree/Modifiers.java b/Robust/src/IR/Tree/Modifiers.java index 7f2ae46e..441d2b3a 100644 --- a/Robust/src/IR/Tree/Modifiers.java +++ b/Robust/src/IR/Tree/Modifiers.java @@ -5,7 +5,7 @@ public class Modifiers { public static final int PROTECTED=2; public static final int PRIVATE=4; public static final int STATIC=8; -// ABSTRACT=16 + public static final int ABSTRACT=16; public static final int FINAL=32; public static final int NATIVE=64; public static final int SYNCHRONIZED=128; @@ -34,6 +34,10 @@ public class Modifiers { public boolean isAtomic() { return ((value&ATOMIC)!=0); } + + public boolean isAbstract() { + return ((value&ABSTRACT)!=0); + } public boolean isSynchronized() { return ((value&SYNCHRONIZED)!=0); @@ -69,6 +73,8 @@ public class Modifiers { st+="synchronized "; if ((value&ATOMIC)!=0) st+="atomic "; + if ((value&ABSTRACT)!=0) + st+="abstract "; return st; } } diff --git a/Robust/src/IR/Tree/SemanticCheck.java b/Robust/src/IR/Tree/SemanticCheck.java index 0159051f..ba846704 100644 --- a/Robust/src/IR/Tree/SemanticCheck.java +++ b/Robust/src/IR/Tree/SemanticCheck.java @@ -214,6 +214,15 @@ public class SemanticCheck { } public void checkMethod(ClassDescriptor cd, MethodDescriptor md) { + if(state.MGC) { + // TODO add version for normal Java later + /* Check for abstract methods */ + if(md.isAbstract()) { + if(!cd.isAbstract()) { + throw new Error("Error! The non-abstract Class " + cd.getSymbol() + "contains an abstract method " + md.getSymbol()); + } + } + } /* Check return type */ if (!md.isConstructor()) if (!md.getReturnType().isVoid()) diff --git a/Robust/src/Parse/java14.cup b/Robust/src/Parse/java14.cup index 477ea95a..718ef76d 100644 --- a/Robust/src/Parse/java14.cup +++ b/Robust/src/Parse/java14.cup @@ -715,7 +715,7 @@ modifier ::= PROTECTED {: RESULT=new ParseNode("protected"); :}| PRIVATE {: RESULT=new ParseNode("private"); :}| STATIC {: RESULT=new ParseNode("static"); :} | -// ABSTRACT | + ABSTRACT {: RESULT=new ParseNode("abstract"); :} | FINAL {: RESULT=new ParseNode("final"); :}| NATIVE {: RESULT=new ParseNode("native"); :} | SYNCHRONIZED {: RESULT=new ParseNode("synchronized"); :} | diff --git a/Robust/src/Tests/AbstractTest.java b/Robust/src/Tests/AbstractTest.java new file mode 100644 index 00000000..044f8569 --- /dev/null +++ b/Robust/src/Tests/AbstractTest.java @@ -0,0 +1,88 @@ +//: interfaces/music4/Music4.java +// Abstract classes and methods. + +abstract class Instrument { + public Instrument(){} + private int i; // Storage allocated for each + public abstract void play(int n); + public String what() { return "Instrument"; } + public abstract void adjust(); +} + +class Wind extends Instrument { + public Wind(){} + public void play(int n) { + System.out.println("Wind.play() " + n); + } + public String what() { return "Wind"; } + public void adjust() {} +} + +class Percussion extends Instrument { + public Percussion(){} + public void play(int n) { + System.out.println("Percussion.play() " + n); + } + public String what() { return "Percussion"; } + public void adjust() {} +} + +class Stringed extends Instrument { + public Stringed(){} + public void play(int n) { + System.out.println("Stringed.play() " + n); + } + public String what() { return "Stringed"; } + public void adjust() {} +} + +class Brass extends Wind { + public Brass(){} + public void play(int n) { + System.out.println("Brass.play() " + n); + } + public void adjust() { System.out.println("Brass.adjust()"); } +} + +class Woodwind extends Wind { + public Woodwind(){} + public void play(int n) { + System.out.println("Woodwind.play() " + n); + } + public String what() { return "Woodwind"; } +} + + +public class AbstractTest { + + public AbstractTest() {} + + // Doesnât care about type, so new types + // added to the system still work right: + static void tune(Instrument i) { + // ... + i.play(9); + } + static void tuneAll(Instrument[] e) { + for(int k = 0; k < e.length; k++) { + Instrument i = e[k]; + tune(i); + } + } + public static void main(String[] args) { + // Upcasting during addition to the array: + Instrument[] orchestra = new Instrument[5]; + orchestra[0] = new Wind(); + orchestra[1] = new Percussion(); + orchestra[2] = new Stringed(); + orchestra[3] = new Brass(); + orchestra[4] = new Woodwind(); + tuneAll(orchestra); + } +} /* Output: +Wind.play() MIDDLE_C +Percussion.play() MIDDLE_C +Stringed.play() MIDDLE_C +Brass.play() MIDDLE_C +Woodwind.play() MIDDLE_C +*///:~ -- 2.34.1