This update:
authorbdemsky <bdemsky>
Sat, 3 Nov 2007 03:37:10 +0000 (03:37 +0000)
committerbdemsky <bdemsky>
Sat, 3 Nov 2007 03:37:10 +0000 (03:37 +0000)
Adds support for using the "+" operator to combine strings...

Robust/src/ClassLibrary/String.java
Robust/src/IR/Flat/BuildCode.java
Robust/src/IR/Flat/BuildFlat.java
Robust/src/IR/Operation.java
Robust/src/IR/Tree/BuildIR.java
Robust/src/IR/Tree/SemanticCheck.java
Robust/src/IR/TypeDescriptor.java
Robust/src/IR/TypeUtil.java
Robust/src/Lex/Keyword.java
Robust/src/Lex/Lexer.java
Robust/src/Parse/java14.cup

index 689d3cf9f2c28df5bfd1d5ebb2a6b1153eaf025b..4d4dfc507fc30dfab8611fa00d267420d770d1bb 100644 (file)
@@ -15,7 +15,7 @@ public class String {
        this.count=str.length;
        this.offset=0;
     }
-
+    
     public String(byte str[]) {
        char charstr[]=new char[str.length];
        for(int i=0;i<str.length;i++)
@@ -58,6 +58,21 @@ public class String {
        return this.lastindexOf(ch, count - 1);
     }
 
+    public String concat(String str) {
+       String newstr=new String();
+       newstr.count=this.count+str.count;
+       char charstr[]=new char[newstr.count];
+       newstr.value=charstr;
+       newstr.offset=0;
+       for(int i=0;i<count;i++) {
+           charstr[i]=value[i+offset];
+       }
+       for(int i=0;i<str.count;i++) {
+           charstr[i+count]=str.value[i+str.offset];
+       }
+       return newstr;
+    }
+
     public int lastindexOf(int ch, int fromIndex) {
        for(int i=fromIndex;i>0;i--)
            if (this.charAt(i)==ch)
@@ -141,7 +156,10 @@ public class String {
     }
 
     public static String valueOf(Object o) {
-       return o.toString();
+       if (o==null)
+           return "null";
+       else
+           return o.toString();
     }
 
     public static String valueOf(int x) {
index 2d8db249ca11ef364a06cab0c7e62e4ffe1c9fe0..789db3ed79885dc081133602b9d627fd7095df7d 100644 (file)
@@ -754,7 +754,7 @@ public class BuildCode {
        for(int i=0;i<fm.numParameters();i++) {
            TempDescriptor temp=fm.getParameter(i);
            TypeDescriptor type=temp.getType();
-           if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
+           if (type.isPtr()&&GENERATEPRECISEGC)
                objectparams.addPtr(temp);
            else
                objectparams.addPrim(temp);
@@ -785,7 +785,7 @@ public class BuildCode {
            for(int i=0;i<writes.length;i++) {
                TempDescriptor temp=writes[i];
                TypeDescriptor type=temp.getType();
-               if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
+               if (type.isPtr()&&GENERATEPRECISEGC)
                    objecttemps.addPtr(temp);
                else
                    objecttemps.addPrim(temp);
@@ -800,7 +800,7 @@ public class BuildCode {
            for(Iterator<TempDescriptor> tmpit=backuptable.values().iterator();tmpit.hasNext();) {
                TempDescriptor tmp=tmpit.next();
                TypeDescriptor type=tmp.getType();
-               if ((type.isPtr()||type.isArray())&&GENERATEPRECISEGC)
+               if (type.isPtr()&&GENERATEPRECISEGC)
                    objecttemps.addPtr(tmp);
                else
                    objecttemps.addPrim(tmp);
@@ -836,7 +836,7 @@ public class BuildCode {
                TypeDescriptor type=fd.getType();
                if (state.DSM&&fd.isGlobal()) //Don't GC the global objects for now
                    continue;
-               if (type.isPtr()||type.isArray())
+               if (type.isPtr())
                    count++;
            }
            output.print(count);
@@ -846,7 +846,7 @@ public class BuildCode {
                TypeDescriptor type=fd.getType();
                if (state.DSM&&fd.isGlobal()) //Don't GC the global objects for now
                    continue;
-               if (type.isPtr()||type.isArray()) {
+               if (type.isPtr()) {
                    output.println(",");
                    output.print("((unsigned int)&(((struct "+cn.getSafeSymbol() +" *)0)->"+fd.getSafeSymbol()+"))");
                }
@@ -1663,8 +1663,7 @@ public class BuildCode {
                String src=generateTemp(fm, ffn.getSrc(),lb);
                String dst=generateTemp(fm, ffn.getDst(),lb);
                    
-               if (ffn.getField().getType().isPtr()||
-                   ffn.getField().getType().isArray()) {
+               if (ffn.getField().getType().isPtr()) {
 
                    //TODO: Uncomment this when we have runtime support
                    //if (ffn.getSrc()==ffn.getDst()) {
@@ -1832,7 +1831,9 @@ public class BuildCode {
            output.println(generateTemp(fm, fon.getDest(),lb)+" = -"+generateTemp(fm, fon.getLeft(),lb)+";");
        else if (fon.getOp().getOp()==Operation.LOGIC_NOT)
            output.println(generateTemp(fm, fon.getDest(),lb)+" = !"+generateTemp(fm, fon.getLeft(),lb)+";");
-       else
+       else if (fon.getOp().getOp()==Operation.ISAVAILABLE) {
+           output.println(generateTemp(fm, fon.getDest(),lb)+" = "+generateTemp(fm, fon.getLeft(),lb)+"->fses==NULL;");
+       } else
            output.println(generateTemp(fm, fon.getDest(),lb)+fon.getOp().toString()+generateTemp(fm, fon.getLeft(),lb)+";");
     }
 
index a651fb1b58dc65ca53229f9e21aadaffa149c809..d873cbe8a58ddb1d4f9a3d357cfffebeb0ef3219 100644 (file)
@@ -618,32 +618,7 @@ public class BuildFlat {
        TempDescriptor temp_right=null;
 
        Operation op=on.getOp();
-       /* We've moved this to assignment nodes
-
-       if (op.getOp()==Operation.POSTINC||
-           op.getOp()==Operation.POSTDEC||
-           op.getOp()==Operation.PREINC||
-           op.getOp()==Operation.PREDEC) {
-           LiteralNode ln=new LiteralNode("int",new Integer(1));
-           ln.setType(new TypeDescriptor(TypeDescriptor.INT));
-           
-           AssignmentNode an=new AssignmentNode(on.getLeft(),
-                                                new OpNode(on.getLeft(),ln, 
-                                                           new Operation((op.getOp()==Operation.POSTINC||op.getOp()==Operation.PREINC)?Operation.PLUS:Operation.MINUS))
-                                                );
-           if (op.getOp()==Operation.POSTINC||
-               op.getOp()==Operation.POSTDEC) {
-               //Can't do, this could have side effects
-               NodePair left=flattenExpressionNode(on.getLeft(),out_temp);
-               NodePair assign=flattenAssignmentNode(an,temp_left);
-               left.getEnd().addNext(assign.getBegin());
-               return new NodePair(left.getBegin(),assign.getEnd());
-           } else {
-               NodePair assign=flattenAssignmentNode(an,out_temp);
-               return assign;
-           }
-           } */
-       
+
        NodePair left=flattenExpressionNode(on.getLeft(),temp_left);
        NodePair right;
        if (on.getRight()!=null) {
@@ -680,6 +655,14 @@ public class BuildFlat {
            fcb.addFalseNext(fon1);
            fon1.addNext(fnop);
            return new NodePair(left.getBegin(), fnop);
+       } else if (op.getOp()==Operation.ADD&&on.getLeft().getType().isString()) {
+           //We have a string concatenate
+           ClassDescriptor stringcd=typeutil.getClass(TypeUtil.StringClass);
+           MethodDescriptor concatmd=typeutil.getMethod(stringcd, "concat", new TypeDescriptor[] {new TypeDescriptor(stringcd)});
+           FlatCall fc=new FlatCall(concatmd, out_temp, temp_left, new TempDescriptor[] {temp_right});
+           left.getEnd().addNext(right.getBegin());
+           right.getEnd().addNext(fc);
+           return new NodePair(left.getBegin(), fc);
        }
 
        FlatOpNode fon=new FlatOpNode(out_temp,temp_left,temp_right,op);
index 274c0414730d9d330a8a6ed73f231627880d47a9..1ea7a3e7a8d2cababe98c80bf8d011ed8a44ac89 100644 (file)
@@ -26,6 +26,7 @@ public class Operation {
     public static final int PREINC=23;
     public static final int PREDEC=24;
     public static final int LOGIC_NOT=25;
+    public static final int ISAVAILABLE=26;
     /* Flat Operations */
     public static final int ASSIGN=100;
 
index 5f17f23b48a873f82698d42bf4bbdc89fc1659af..08c113d2009640c4d4cc5f7de589ee4d6a8d2435 100644 (file)
@@ -431,6 +431,9 @@ public class BuildIR {
        } else if (isNode(pn,"this")) {
            NameDescriptor nd=new NameDescriptor("this");
            return new NameNode(nd);
+       } else if (isNode(pn,"isavailable")) {
+           NameDescriptor nd=new NameDescriptor(pn.getTerminal());
+           return new OpNode(new NameNode(nd),null,new Operation(Operation.ISAVAILABLE));
        } else if (isNode(pn,"methodinvoke1")) {
            NameDescriptor nd=parseName(pn.getChild("name"));
            Vector args=parseArgumentList(pn);
index 5e1c2d23bfe63dcf8b5d28a0ebfb1a198fd2de56..84e18d9b3da8cbe43bf81a974a382a923c0b8e3f 100644 (file)
@@ -609,14 +609,14 @@ public class SemanticCheck {
                if (bestmd==null)
                    bestmd=currmd;
                else {
-                   if (isMoreSpecific(currmd,bestmd)) {
+                   if (typeutil.isMoreSpecific(currmd,bestmd)) {
                        bestmd=currmd;
                    } else if (con.isGlobal()&&match(currmd, bestmd)) {
                        if (currmd.isGlobal()&&!bestmd.isGlobal())
                            bestmd=currmd;
                        else if (currmd.isGlobal()&&bestmd.isGlobal())
                            throw new Error();
-                   } else if (!isMoreSpecific(bestmd, currmd)) {
+                   } else if (!typeutil.isMoreSpecific(bestmd, currmd)) {
                        throw new Error("No method is most specific");
                    }
                    
@@ -630,27 +630,6 @@ public class SemanticCheck {
     }
 
 
-    /** Check to see if md1 is more specific than md2...  Informally
-       if md2 could always be called given the arguments passed into
-       md1 */
-
-    boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
-       /* Checks if md1 is more specific than md2 */
-       if (md1.numParameters()!=md2.numParameters())
-           throw new Error();
-       for(int i=0;i<md1.numParameters();i++) {
-           if (!typeutil.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
-               return false;
-       }
-       if (!typeutil.isSuperorType(md2.getReturnType(), md1.getReturnType()))
-               return false;
-
-       if (!typeutil.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
-               return false;
-
-       return true;
-    }
-
     /** Check to see if md1 is the same specificity as md2.*/
 
     boolean match(MethodDescriptor md1, MethodDescriptor md2) {
@@ -737,9 +716,9 @@ public class SemanticCheck {
            if (bestmd==null)
                bestmd=currmd;
            else {
-               if (isMoreSpecific(currmd,bestmd)) {
+               if (typeutil.isMoreSpecific(currmd,bestmd)) {
                    bestmd=currmd;
-               } else if (!isMoreSpecific(bestmd, currmd))
+               } else if (!typeutil.isMoreSpecific(bestmd, currmd))
                    throw new Error("No method is most specific");
                
                /* Is this more specific than bestmd */
@@ -807,6 +786,14 @@ public class SemanticCheck {
            on.setType(lefttype);
            break;
 
+       case Operation.ISAVAILABLE:
+           if (!(ltd.isPtr())) {
+               throw new Error("Can't use isavailable on non-pointers/non-parameters.");
+           }
+           lefttype=ltd;
+           on.setLeftType(lefttype);
+           on.setType(new TypeDescriptor(TypeDescriptor.BOOLEAN));
+           break;
        case Operation.EQUAL:
        case Operation.NOTEQUAL:
            // 5.6.2 Binary Numeric Promotion
@@ -815,8 +802,8 @@ public class SemanticCheck {
                if (!(ltd.isBoolean()&&rtd.isBoolean()))
                    throw new Error();
                righttype=lefttype=new TypeDescriptor(TypeDescriptor.BOOLEAN);
-           } else if (ltd.isPtr()||ltd.isArray()||rtd.isPtr()||rtd.isArray()) {
-               if (!((ltd.isPtr()||ltd.isArray())&&(rtd.isPtr()||rtd.isArray())))
+           } else if (ltd.isPtr()||rtd.isPtr()) {
+               if (!(ltd.isPtr()&&rtd.isPtr()))
                    throw new Error();
                righttype=rtd;
                lefttype=ltd;
@@ -860,8 +847,24 @@ public class SemanticCheck {
            break;
 
        case Operation.ADD:
-           //TODO: Need special case for strings eventually
-           
+           if (ltd.isString()||rtd.isString()) {
+               ClassDescriptor stringcl=typeutil.getClass(TypeUtil.StringClass);
+               TypeDescriptor stringtd=new TypeDescriptor(stringcl);
+               NameDescriptor nd=new NameDescriptor("String");
+               NameDescriptor valuend=new NameDescriptor(nd, "valueOf");
+               MethodInvokeNode leftmin=new MethodInvokeNode(valuend);
+               MethodInvokeNode rightmin=new MethodInvokeNode(valuend);
+               leftmin.addArgument(on.getLeft());
+               rightmin.addArgument(on.getRight());
+               on.left=leftmin;
+               on.right=rightmin;
+               checkExpressionNode(md, nametable, on.getLeft(), null);
+               checkExpressionNode(md, nametable, on.getRight(), null);
+               on.setLeftType(stringtd);
+               on.setRightType(stringtd);
+               on.setType(stringtd);
+               break;
+           }
            
        case Operation.SUB:
        case Operation.MULT:
index 04a717ed0161d78d669cf295a64186760c6f1b6c..06c7bdd56d591c6c24e34473cd438abb82f2986d 100644 (file)
@@ -39,6 +39,16 @@ public class TypeDescriptor extends Descriptor {
        return false;
     }
 
+    public boolean isString() {
+       if (type!=CLASS)
+           return false;
+       if (arraycount>0)
+           return false;
+       if (!getSymbol().equals(TypeUtil.StringClass))
+           return false;
+       return true;
+    }
+
     public int hashCode() {
        int hashcode=type^arraycount;
        if (type==CLASS)
index e5ce84bc70fda79a0df2e37c9ccbcfad1aaf2949..dae65785924414ee91e8a8b5d1cd89bd5f177b7e 100644 (file)
@@ -72,6 +72,55 @@ public class TypeUtil {
        throw new Error(cd+" has no main");
     }
 
+    /** Check to see if md1 is more specific than md2...  Informally
+       if md2 could always be called given the arguments passed into
+       md1 */
+
+    public boolean isMoreSpecific(MethodDescriptor md1, MethodDescriptor md2) {
+       /* Checks if md1 is more specific than md2 */
+       if (md1.numParameters()!=md2.numParameters())
+           throw new Error();
+       for(int i=0;i<md1.numParameters();i++) {
+           if (!this.isSuperorType(md2.getParamType(i), md1.getParamType(i)))
+               return false;
+       }
+       if (!this.isSuperorType(md2.getReturnType(), md1.getReturnType()))
+               return false;
+
+       if (!this.isSuperorType(md2.getClassDesc(), md1.getClassDesc()))
+               return false;
+
+       return true;
+    }
+
+    public MethodDescriptor getMethod(ClassDescriptor cd, String name, TypeDescriptor[] types) {
+       Set methoddescriptorset=cd.getMethodTable().getSet(name);
+        MethodDescriptor bestmd=null;
+        NextMethod:
+        for(Iterator methodit=methoddescriptorset.iterator();methodit.hasNext();) {
+            MethodDescriptor currmd=(MethodDescriptor)methodit.next();
+            /* Need correct number of parameters */
+            if (types.length!=currmd.numParameters())
+                continue;
+            for(int i=0;i<types.length;i++) {
+                if (!this.isSuperorType(currmd.getParamType(i),types[i]))
+                    continue NextMethod;
+            }
+            /* Method okay so far */
+            if (bestmd==null)
+                bestmd=currmd;
+            else {
+                if (isMoreSpecific(currmd,bestmd)) {
+                    bestmd=currmd;
+                } else if (!isMoreSpecific(bestmd, currmd))
+                    throw new Error("No method is most specific");
+                
+                /* Is this more specific than bestmd */
+            }
+        }
+       return bestmd;
+    }
+
     public void createFullTable() {
        subclasstable=new Hashtable();
     
@@ -184,10 +233,10 @@ public class TypeUtil {
            
            return false;
        } else if (possiblesuper.isPrimitive()&&(!possiblesuper.isArray())&&
-                  (cd2.isArray()||cd2.isPtr()))
+                  cd2.isPtr())
            return false;
        else if (cd2.isPrimitive()&&(!cd2.isArray())&&
-                (possiblesuper.isArray()||possiblesuper.isPtr()))
+                possiblesuper.isPtr())
            return false;
        else
            throw new Error("Case not handled:"+possiblesuper+" "+cd2);
index 7d6ca9094eb02703213c85a655551c797c31f4be..f39079a1a435376f2d86ecebe68debb5ee8e8a4d 100644 (file)
@@ -42,6 +42,7 @@ class Keyword extends Token {
     key_table.put("import", new Integer(Sym.IMPORT));
     key_table.put("instanceof", new Integer(Sym.INSTANCEOF));
     key_table.put("int", new Integer(Sym.INT));
+    key_table.put("isavailable", new Integer(Sym.ISAVAILABLE));
     key_table.put("long", new Integer(Sym.LONG));
     key_table.put("native", new Integer(Sym.NATIVE));
     key_table.put("new", new Integer(Sym.NEW));
index 2cdd84e9da8f3d27a26ce86d041ebf868f13f403..1d7e461026fe987f4e0e7722215955f527a672cd 100644 (file)
@@ -249,7 +249,8 @@ public class Lexer {
     "extends", "external", "final", "finally", 
     "flag", //keyword for failure aware computation
     "float", "for", "global", "goto", "if", 
-    "implements", "import", "instanceof", "int", "interface", "long",  
+    "implements", "import", "instanceof", "int", "interface", "isavailable",
+    "long",  
     "native", "new", "optional", "package", "private", "protected", "public", 
     "return", "short", "static", "strictfp", "super", "switch", "synchronized",
     "tag", "task", "taskexit", //keywords for failure aware computation
index 0f3afd38c0044a61f823927b578595f4bfe68964..d071f337550d10eb570363c2cfd73e69730c35b2 100644 (file)
@@ -222,6 +222,7 @@ non terminal ParseNode expression_opt, expression;
 //failure aware computation keywords
 terminal FLAG;
 terminal OPTIONAL;
+terminal ISAVAILABLE;
 terminal EXTERNAL;
 terminal TAG;
 terminal TASK;
@@ -1356,6 +1357,11 @@ primary_no_new_array ::=
        |       field_access:exp {: RESULT=exp; :}
        |       method_invocation:exp {: RESULT=exp; :}
        |       array_access:exp {: RESULT=exp; :}
+       |       ISAVAILABLE LPAREN IDENTIFIER:id RPAREN {: 
+               ParseNode pn=new ParseNode("isavailable");
+               pn.addChild(id);
+               RESULT=pn;
+       :}
 //     |       primitive_type DOT CLASS
 //     |       VOID DOT CLASS
 //     |       array_type DOT CLASS