X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=Repair%2FRepairCompiler%2FMCC%2FIR%2FDotExpr.java;h=6998d3a3f001d8edb46ff6c5196380631c77ef97;hb=e8e7caf9f4a4e0c49fdfe97fc529703ebd8a4d8c;hp=b5d0243630c93e7d88eb3eae0ee3e492361f14ce;hpb=9ca8c9d22f76bfce410cd3762a856ef5c0f1963f;p=repair.git diff --git a/Repair/RepairCompiler/MCC/IR/DotExpr.java b/Repair/RepairCompiler/MCC/IR/DotExpr.java index b5d0243..6998d3a 100755 --- a/Repair/RepairCompiler/MCC/IR/DotExpr.java +++ b/Repair/RepairCompiler/MCC/IR/DotExpr.java @@ -1,13 +1,93 @@ package MCC.IR; import java.util.*; +import MCC.Compiler; public class DotExpr extends Expr { - + Expr left; String field; Expr index; + static boolean DOMEMCHECKS=false; + static boolean DOTYPECHECKS=false; + static boolean DONULL=false; + + + public DotExpr(Expr left, String field, Expr index) { + this.left = left; + this.field = field; + this.index = index; + } + + public boolean isInvariant(Set vars) { + if (!left.isInvariant(vars)) + return false; + if (intindex!=null) + return intindex.isInvariant(vars); + else + return true; + } + + public Set findInvariants(Set vars) { + if (isInvariant(vars)) { + Set s=new HashSet(); + s.add(this); + return s; + } else { + Set ls=left.findInvariants(vars); + if (intindex!=null) { + ls.addAll(intindex.findInvariants(vars)); + Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound(); + ls.addAll(indexbound.findInvariants(vars)); + if ((!(intindex instanceof IntegerLiteralExpr))|| + ((IntegerLiteralExpr) intindex).getValue() != 0) { + FieldDescriptor fd=this.fd; + if (fd instanceof ArrayDescriptor) + fd=((ArrayDescriptor)fd).getField(); + Expr basesize = fd.getBaseSizeExpr(); + ls.addAll(basesize.findInvariants(vars)); + } + } + return ls; + } + } + + + public boolean isSafe() { + if (!left.isSafe()) + return false; + + FieldDescriptor tmpfd=fd; + + if (tmpfd.getPtr()) // Pointers cound be invalid + return false; + + if (tmpfd instanceof ArrayDescriptor) { + Expr arrayindex=((ArrayDescriptor)tmpfd).getIndexBound(); + if (index instanceof IntegerLiteralExpr&&arrayindex instanceof IntegerLiteralExpr) { + int indexvalue=((IntegerLiteralExpr)index).getValue(); + int arrayindexvalue=((IntegerLiteralExpr)arrayindex).getValue(); + if (indexvalue>=0&&indexvalue Superblock, while, d.b ==> Block - fd = ld.getField(); - assert fd != null; - assert intindex == null; - intindex = ld.getIndex(); - } else { - fieldtype = fd.getType(); - } + StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType(); + Expr offsetbits; - // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor obect that is in teh vector list - // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array + // #ATTN#: getOffsetExpr needs to be called with the fielddescriptor object that is in the vector list + // this means that if the field is an arraydescriptor you have to call getOffsetExpr with the array // descriptor not the underlying field descriptor /* we calculate the offset in bits */ - offsetbits = struct.getOffsetExpr(fd); - if (fd instanceof ArrayDescriptor) { - fd = ((ArrayDescriptor) fd).getField(); - } - + offsetbits = struct.getOffsetExpr(fd); + + FieldDescriptor fd=this.fd; + if (fd instanceof ArrayDescriptor) + fd=((ArrayDescriptor)fd).getField(); + boolean doboundscheck=true; + boolean performedboundscheck=false; + + writer.addDeclaration(getType().getGenerateType().toString(),dest.getSafeSymbol()); + writer.outputline(dest.getSafeSymbol()+"=0;"); + if (intindex != null) { if (intindex instanceof IntegerLiteralExpr && ((IntegerLiteralExpr) intindex).getValue() == 0) { - /* short circuit for constant 0 */ + /* short circuit for constant 0 */ } else { Expr basesize = fd.getBaseSizeExpr(); - offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex)); + if (doboundscheck) { + VarDescriptor indexvd=VarDescriptor.makeNew("index"); + indexvd.setType(ReservedTypeDescriptor.INT); + writer.getSymbolTable().add(indexvd); + + writer.output("/* " + indexvd.getSafeSymbol() + " <-- "); + + intindex.prettyPrint(writer); + writer.outputline("*/"); + intindex.generate(writer, indexvd); + writer.output("/* " + indexvd.getSafeSymbol() + " = "); + intindex.prettyPrint(writer); + writer.outputline("*/"); + Expr indexbound=((ArrayDescriptor)this.fd).getIndexBound(); + VarDescriptor indexboundvd=VarDescriptor.makeNew("indexbound"); + + indexbound.generate(writer,indexboundvd); + + writer.outputline("if ("+indexvd.getSafeSymbol()+">=0 &&"+indexvd.getSafeSymbol()+"<"+indexboundvd.getSafeSymbol()+")"); + writer.startblock(); + VarExpr indexve=new VarExpr(indexvd); + offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, indexve)); + + performedboundscheck=true; + } else + offsetbits = new OpExpr(Opcode.ADD, offsetbits, new OpExpr(Opcode.MULT, basesize, intindex)); } } - - final SymbolTable st = writer.getSymbolTable(); - TypeDescriptor td = offsetbits.typecheck(new SemanticAnalyzer() { - public IRErrorReporter getErrorReporter() { throw new IRException("badness"); } - public SymbolTable getSymbolTable() { return st; } - }); - - if (td == null) { - throw new IRException(); - } else if (td != ReservedTypeDescriptor.INT) { - throw new IRException(); - } - - // #TBD#: ptr's to bits and byte's and stuff are a little iffy... - // right now, a bit* is the same as a int* = short* = byte* (that is there - // is no post-derefernce mask) - - // #ATTN#: do we handle int* correctly? what is the correct behavior? we automatically - // dereference pointers, but for structures that means that if we have a nested structure - // we return an integer address to that nested structure. if we have a pointer to a - // structure else where we want that base address ... yeah so we *(int *) it... ok we are - // correct - boolean dotypecheck = false; + final SymbolTable st = writer.getSymbolTable(); + TypeDescriptor td2 = offsetbits.typecheck(new SemanticAnalyzer() { + public IRErrorReporter getErrorReporter() { throw new IRException("badness"); } + public SymbolTable getSymbolTable() { return st; } + }); - if (offsetbits instanceof IntegerLiteralExpr) { - int offsetinbits = ((IntegerLiteralExpr) offsetbits).getValue(); - int offset = offsetinbits >> 3; /* offset in bytes */ - - if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) { - int shift = offsetinbits - (offset << 3); - int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue()); - - /* type var = ((*(int *) (base + offset)) >> shift) & mask */ - writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() + - " = ((*(int *)" + - "(" + leftd.getSafeSymbol() + " + " + offset + ")) " + - " >> " + shift + ") & 0x" + Integer.toHexString(mask) + ";"); - } else { /* a structure address or a ptr! */ - String ptr = fd.getPtr() ? "*(int *)" : ""; - /* type var = [*(int *)] (base + offset) */ - - // #ATTN: was 'getType.getGeneratedType()' instead of 'int' but all pointers are represented - // by integers - writer.outputline("int " + dest.getSafeSymbol() + - " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset + ");"); - - dotypecheck = true; - } - } else { /* offset in bits is an expression that must be generated */ - VarDescriptor ob = VarDescriptor.makeNew("offsetinbits"); - writer.output("// " + ob.getSafeSymbol() + " <-- "); - offsetbits.prettyPrint(writer); - writer.outputline(""); - offsetbits.generate(writer, ob); - writer.output("// " + ob.getSafeSymbol() + " = "); - offsetbits.prettyPrint(writer); - writer.outputline(""); - - /* derive offset in bytes */ - VarDescriptor offset = VarDescriptor.makeNew("offset"); - writer.outputline("int " + offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;"); - - if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) { - VarDescriptor shift = VarDescriptor.makeNew("shift"); - writer.outputline("int " + shift.getSafeSymbol() + " = " + ob.getSafeSymbol() + - " - (" + offset.getSafeSymbol() + " << 3);"); - int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue()); - - /* type var = ((*(int *) (base + offset)) >> shift) & mask */ - writer.outputline(getType().getGenerateType() + " " + dest.getSafeSymbol() + - " = ((*(int *)" + - "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " + - " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";"); - } else { /* a structure address or a ptr */ - String ptr = fd.getPtr() ? "*(int *)" : ""; - /* type var = [*(int *)] (base + offset) */ - - // #ATTN: was 'getType.getGeneratedType()' instead of 'int' but all pointers are represented - // by integers - writer.outputline("int " + dest.getSafeSymbol() + - " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");"); - dotypecheck = true; - } - } - - - if (dotypecheck) { /* typemap checks! */ - // dest is 'low' - // high is 'low' + sizeof(fd.getDataStructure) <<< can be cached!! - - // #ATTN#: we need to get the size of the fieldtype (if its a label the type of the label, not the - // underlying field's type + if (td2 == null) { + throw new IRException(); + } else if (td2 != ReservedTypeDescriptor.INT) { + throw new IRException(); + } - Expr sizeofexpr = fieldtype.getSizeExpr(); - VarDescriptor sizeof = VarDescriptor.makeNew("sizeof"); - sizeofexpr.generate(writer, sizeof); + boolean dotypecheck = false; - String low = dest.getSafeSymbol(); - String high = VarDescriptor.makeNew("high").getSafeSymbol(); - writer.outputline("int " + high + " = " + low + " + " + sizeof.getSafeSymbol() + ";"); - writer.outputline("assertvalidmemory(" + low + ", " + high + ");"); + VarDescriptor ob = VarDescriptor.makeNew("offsetinbits"); + writer.output("/* " + ob.getSafeSymbol() + " <-- "); + offsetbits.prettyPrint(writer); + writer.outputline("*/"); + offsetbits.generate(writer, ob); + writer.output("/* " + ob.getSafeSymbol() + " = "); + offsetbits.prettyPrint(writer); + writer.outputline("*/"); + + /* derive offset in bytes */ + VarDescriptor offset = VarDescriptor.makeNew("offset"); + writer.addDeclaration("int", offset.getSafeSymbol()); + writer.outputline(offset.getSafeSymbol() + " = " + ob.getSafeSymbol() + " >> 3;"); + + if (fd.getType() instanceof ReservedTypeDescriptor && !fd.getPtr()) { + VarDescriptor shift = VarDescriptor.makeNew("shift"); + writer.addDeclaration("int", shift.getSafeSymbol()); + writer.outputline(shift.getSafeSymbol() + " = " + ob.getSafeSymbol() + + " - (" + offset.getSafeSymbol() + " << 3);"); + int mask = bitmask(((IntegerLiteralExpr)fd.getType().getSizeExpr()).getValue()); + + /* type var = ((*(int *) (base + offset)) >> shift) & mask */ + writer.outputline("if ("+leftd.getSafeSymbol()+")"); + writer.outputline(dest.getSafeSymbol() + " = ((*(int *)" + + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")) " + + " >> " + shift.getSafeSymbol() + ") & 0x" + Integer.toHexString(mask) + ";"); + writer.outputline("else maybe=1;"); + } else { /* a structure address or a ptr */ + String ptr = fd.getPtr() ? "*(int *)" : ""; + /* type var = [*(int *)] (base + offset) */ + writer.outputline("if ("+leftd.getSafeSymbol()+")"); + writer.startblock(); + writer.outputline(dest.getSafeSymbol() + + " = " + ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ");"); + if (fd.getPtr()) { + writer.outputline("if ("+dest.getSafeSymbol()+")"); + writer.startblock(); + + + if (DOTYPECHECKS||DOMEMCHECKS) { + /* NEED TO CHECK IF THERE ARE VARIABLES TO PLAY WITH IN THE STRUCT!!!! */ + if (Compiler.EXACTALLOCATION&&exactalloc(td)) { + writer.outputline("if (!assertexactmemory("+dest.getSafeSymbol()+", "+this.td.getId()+"))"); + { + writer.startblock(); + /* Okay, we've failed to fit it in here */ + + VarDescriptor highptr=VarDescriptor.makeNew("highptr"); + writer.addDeclaration("int", highptr.getSafeSymbol()); + writer.outputline(highptr.getSafeSymbol()+"=getendofblock("+dest.getSafeSymbol()+");"); + VarDescriptor size=VarDescriptor.makeNew("size"); + writer.addDeclaration("int", size.getSafeSymbol()); + writer.outputline(size.getSafeSymbol()+"="+highptr.getSafeSymbol()+"-"+dest.getSafeSymbol()+";"); + + StructureTypeDescriptor std=(StructureTypeDescriptor)this.td; + ArrayDescriptor afd=(ArrayDescriptor)std.get(0); + TypeDescriptor elementdescriptor=afd.getType(); + Expr sizeexpr=elementdescriptor.getSizeExpr(); + int elementsize=OpExpr.getInt(sizeexpr); + //convert size to bytes + if (elementsize%8==0) + elementsize=elementsize/8; + else + elementsize=(elementsize/8)+1; + /* Basic sanity check */ + writer.outputline("if ("+size.getSafeSymbol()+"%"+ + elementsize+"==0)"); + { + writer.startblock(); + VarDescriptor numElements=VarDescriptor.makeNew("numberofelements"); + writer.addDeclaration("int", numElements.getSafeSymbol()); + writer.outputline(numElements.getSafeSymbol()+"="+size.getSafeSymbol()+"/"+elementsize+";"); + Expr indexbound=afd.getIndexBound(); + if (indexbound instanceof DotExpr) { + /* NEED TO IMPLEMENT */ + + VarExpr ve=new VarExpr(numElements); + numElements.setType(ReservedTypeDescriptor.INT); + ve.td=ReservedTypeDescriptor.INT; + Updates u=new Updates(indexbound,ve); + UpdateNode un=new UpdateNode(null); + un.addUpdate(u); + un.generate(writer,false,false,null,null,null,null); + writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");"); + writer.outputline("computesizes(thisvar);"); + writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);"); + writer.outputline("goto rebuild;"); + + // writer.outputline("break;"); + + } else if ((indexbound instanceof OpExpr)&& + (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&& + (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&& + (((OpExpr)indexbound).getRightExpr() instanceof DotExpr)) { + + DotExpr leftexpr=(DotExpr)(((OpExpr)indexbound).getLeftExpr()); + VarDescriptor leftside=VarDescriptor.makeNew("leftvalue"); + writer.addDeclaration("int", leftside.getSafeSymbol()); + leftexpr.generate(writer,leftside); + DotExpr rightexpr=(DotExpr)(((OpExpr)indexbound).getRightExpr()); + VarDescriptor rightside=VarDescriptor.makeNew("rightvalue"); + writer.addDeclaration("int", rightside.getSafeSymbol()); + rightexpr.generate(writer,rightside); + writer.outputline("if (("+leftside.getSafeSymbol()+"!=0) &&("+numElements.getSafeSymbol()+"%"+leftside.getSafeSymbol()+"==0))"); + { + writer.startblock(); + VarDescriptor newvalue=VarDescriptor.makeNew("newvalue"); + writer.addDeclaration("int", newvalue.getSafeSymbol()); + writer.outputline(newvalue.getSafeSymbol()+"="+numElements.getSafeSymbol()+"/"+leftside.getSafeSymbol()+";"); + VarExpr ve=new VarExpr(newvalue); + newvalue.setType(ReservedTypeDescriptor.INT); + ve.td=ReservedTypeDescriptor.INT; + Updates u=new Updates(rightexpr,ve); + UpdateNode un=new UpdateNode(null); + un.addUpdate(u); + un.generate(writer,false,false,null,null,null,null); + writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");"); + writer.outputline("computesizes(thisvar);"); + writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);"); + writer.outputline("goto rebuild;"); + // writer.outputline("break;"); + writer.endblock(); + } + writer.outputline("else if (("+rightside.getSafeSymbol()+"!=0)&&("+numElements.getSafeSymbol()+"%"+rightside.getSafeSymbol()+"==0))"); + { + writer.startblock(); + VarDescriptor newvalue=VarDescriptor.makeNew("newvalue"); + writer.addDeclaration("int", newvalue.getSafeSymbol()); + writer.outputline(newvalue.getSafeSymbol()+"="+numElements.getSafeSymbol()+"/"+rightside.getSafeSymbol()+";"); + VarExpr ve=new VarExpr(newvalue); + newvalue.setType(ReservedTypeDescriptor.INT); + ve.td=ReservedTypeDescriptor.INT; + Updates u=new Updates(leftexpr,ve); + UpdateNode un=new UpdateNode(null); + un.addUpdate(u); + un.generate(writer,false,false,null,null,null,null); + writer.outputline("free"+RepairGenerator.name+"("+RepairGenerator.newmodel.getSafeSymbol()+");"); + writer.outputline("computesizes(thisvar);"); + writer.outputline(RepairGenerator.name+"_staterecomputesizes(thisvar);"); + writer.outputline("goto rebuild;"); + // writer.outputline("break;"); + writer.endblock(); + } + + + } else throw new Error("Should be here"); + + writer.endblock(); + } + + writer.endblock(); + } + /* + + if (indexbound instanceof DotExpr) + return true; + if ((indexbound instanceof OpExpr)&& + (((OpExpr)indexbound).getOpcode()==Opcode.MULT)&& + (((OpExpr)indexbound).getLeftExpr() instanceof DotExpr)&& + (((OpExpr)indexbound).getRightExpr() instanceof DotExpr)) + return true; + return false; + */ + + + /* Give up and null out bad pointer */ + } + VarDescriptor typevar=VarDescriptor.makeNew("typechecks"); + if (DOMEMCHECKS&&(!DOTYPECHECKS)) { + writer.addDeclaration("bool", typevar.getSafeSymbol()); + writer.outputline(typevar.getSafeSymbol()+"=assertvalidmemory(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");"); + dotypecheck = true; + } else if (DOTYPECHECKS) { + writer.addDeclaration("bool", typevar.getSafeSymbol()); + writer.outputline(typevar.getSafeSymbol()+"=assertvalidtype(" + dest.getSafeSymbol() + ", " + this.td.getId() + ");"); + } + if (DOMEMCHECKS||DOTYPECHECKS) { + writer.outputline("if (!"+typevar.getSafeSymbol()+")"); + writer.startblock(); + writer.outputline(dest.getSafeSymbol()+"=0;"); + if (DONULL) + writer.outputline(ptr + "(" + leftd.getSafeSymbol() + " + " + offset.getSafeSymbol() + ")=0;"); + writer.endblock(); + } + } - // we need to null value check and conditionalize the rest of the rule... we'll use a hack - // here where we store the number of indents in this class... and then provide a static - // method to unwind... - //writer.outputline("// assertvalidmemory "); - //DotExpr.memoryindents++; - //writer.outputline("if (" + dest.getSafeSymbol() + " != NULL)"); - //writer.startblock(); + writer.endblock(); + } + writer.endblock(); + writer.outputline("else maybe=1;"); } - + if (performedboundscheck) { + writer.endblock(); + writer.outputline(" else "); + writer.startblock(); + writer.outputline(dest.getSafeSymbol()+"=0;"); + writer.outputline("maybe=1;"); + if (!Compiler.REPAIR) + writer.outputline("printf(\"Array Index Out of Bounds\");"); + writer.endblock(); + } } private int bitmask(int bits) { int mask = 0; - + for (int i = 0; i < bits; i++) { mask <<= 1; mask += 1; } - return mask; + return mask; } public void prettyPrint(PrettyPrinter pp) { @@ -221,10 +512,52 @@ public class DotExpr extends Expr { } } + public boolean isValue(TypeDescriptor td) { + FieldDescriptor tmpfd=fd; + if (tmpfd instanceof ArrayDescriptor) + tmpfd=((ArrayDescriptor)tmpfd).getField(); + return (tmpfd.getPtr()||(tmpfd.getType() instanceof ReservedTypeDescriptor)); + } + + public boolean isPtr() { + FieldDescriptor tmpfd=fd; + if (tmpfd instanceof ArrayDescriptor) + tmpfd=((ArrayDescriptor)tmpfd).getField(); + return tmpfd.getPtr(); + } + + boolean typechecked=false; public TypeDescriptor typecheck(SemanticAnalyzer sa) { + if (typechecked) + return this.td; + else typechecked=true; TypeDescriptor lefttype = left.typecheck(sa); TypeDescriptor indextype = index == null ? null : index.typecheck(sa); + { + /* finished typechecking...so we can fill the fields in */ + StructureTypeDescriptor struct = (StructureTypeDescriptor) left.getType(); + FieldDescriptor fd = struct.getField(field); + LabelDescriptor ld = struct.getLabel(field); + if (ld != null) { /* label */ + assert fd == null; + fieldtype = ld.getType(); // d.s ==> Superblock, while, d.b ==> Block + fd = ld.getField(); + assert fd != null; + assert intindex == null; + intindex = ld.getIndex(); + } else { + if (fd==null) { + throw new Error("Null fd for: "+field); + } + fieldtype = fd.getType(); + intindex=index; + } + this.fd=fd; + if (fieldtype instanceof MissingTypeDescriptor) + throw new Error(fieldtype.getSymbol()+" type undefined!"); + } + if ((lefttype == null) || (index != null && indextype == null)) { return null; } @@ -236,7 +569,7 @@ public class DotExpr extends Expr { } } - if (lefttype instanceof StructureTypeDescriptor) { + if (lefttype instanceof StructureTypeDescriptor) { StructureTypeDescriptor struct = (StructureTypeDescriptor) lefttype; FieldDescriptor fd = struct.getField(field); LabelDescriptor ld = struct.getLabel(field); @@ -246,21 +579,21 @@ public class DotExpr extends Expr { if (indextype == null && fd instanceof ArrayDescriptor) { sa.getErrorReporter().report(null, "Must specify an index what accessing array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'"); - return null; + return null; } else if (indextype != null && !(fd instanceof ArrayDescriptor)) { sa.getErrorReporter().report(null, "Cannot specify an index when accessing non-array field '" + struct.getSymbol() + "." + fd.getSymbol() + "'"); return null; } - + this.td = fd.getType(); } else if (ld != null) { /* label */ assert fd == null; - if (index != null) { + if (index != null) { sa.getErrorReporter().report(null, "A label cannot be accessed as an array"); return null; } - + this.td = ld.getType(); } else { sa.getErrorReporter().report(null, "No such field or label '" + field + "' in structure '" + struct.getSymbol() + "'"); @@ -279,9 +612,5 @@ public class DotExpr extends Expr { sa.getErrorReporter().report(null, "Left hand side of . expression must be a structure type, not '" + lefttype.getSymbol() + "'"); return null; } - - } - } -