From 60377918e96e101d2206df7822b16d717cd28c82 Mon Sep 17 00:00:00 2001 From: angelicalin Date: Thu, 8 Feb 2018 11:11:39 -0600 Subject: [PATCH 1/2] first part done --- .idea/comp394-type-modeling.iml | 9 ++++++++ .idea/misc.xml | 4 ++++ .idea/modules.xml | 8 +++++++ python-attr-lookup/python-attr-lookup.iml | 22 +++++++++++++++++++ .../src/plang/PythonObject.java | 17 ++++++++++---- python-attr-lookup/src/plang/PythonType.java | 10 +++++++-- .../test/plang/PythonObjectTest.java | 1 + 7 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 .idea/comp394-type-modeling.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml diff --git a/.idea/comp394-type-modeling.iml b/.idea/comp394-type-modeling.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/comp394-type-modeling.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..58918f5 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..96bca08 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/python-attr-lookup/python-attr-lookup.iml b/python-attr-lookup/python-attr-lookup.iml index 01e8e1b..e03a82f 100644 --- a/python-attr-lookup/python-attr-lookup.iml +++ b/python-attr-lookup/python-attr-lookup.iml @@ -20,5 +20,27 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/python-attr-lookup/src/plang/PythonObject.java b/python-attr-lookup/src/plang/PythonObject.java index a8e311f..862d818 100644 --- a/python-attr-lookup/src/plang/PythonObject.java +++ b/python-attr-lookup/src/plang/PythonObject.java @@ -50,8 +50,12 @@ public List getMRO() { * Constructs the MRO. Called only once, the first time we need the MRO; this class memoizes the * result (i.e. it remembers the list buildMRO() returned and keeps returning it). */ - protected List buildMRO() { - throw new UnsupportedOperationException("not implemented yet"); + protected List buildMRO(){ + + List list = type.buildMRO(); + list.add(0,this); + return list; + //throw new UnsupportedOperationException("not implemented yet"); } /** @@ -62,7 +66,12 @@ protected List buildMRO() { * @throws PythonAttributeException When there is no attribute on this object with that name. */ public final PythonObject get(String attrName) throws PythonAttributeException { - throw new UnsupportedOperationException("not implemented yet"); + for(PythonObject pobject : getMRO()){ + if(pobject.attrs.containsKey(attrName)){ + return pobject.attrs.get(attrName); + } + } + throw new PythonAttributeException(this,attrName); } /** @@ -74,7 +83,7 @@ public final PythonObject get(String attrName) throws PythonAttributeException { * @param value Its new value */ public final void set(String attrName, PythonObject value) { - throw new UnsupportedOperationException("not implemented yet"); + attrs.put(attrName,value); } @Override diff --git a/python-attr-lookup/src/plang/PythonType.java b/python-attr-lookup/src/plang/PythonType.java index 4e2be4a..fd2d185 100644 --- a/python-attr-lookup/src/plang/PythonType.java +++ b/python-attr-lookup/src/plang/PythonType.java @@ -41,7 +41,12 @@ public PythonObject getBase() { @Override protected List buildMRO() { - throw new UnsupportedOperationException("not implemented yet"); + List list = new ArrayList<>(); + list.add(this); + if(base!= null){ + list.addAll(base.getMRO()); + } + return list; } /** @@ -49,7 +54,8 @@ protected List buildMRO() { * this PythonType. */ public PythonObject instantiate() { - throw new UnsupportedOperationException("not implemented yet"); + return new PythonObject(this); + } @Override diff --git a/python-attr-lookup/test/plang/PythonObjectTest.java b/python-attr-lookup/test/plang/PythonObjectTest.java index 2080d71..179795f 100644 --- a/python-attr-lookup/test/plang/PythonObjectTest.java +++ b/python-attr-lookup/test/plang/PythonObjectTest.java @@ -1,6 +1,7 @@ package plang; import org.junit.jupiter.api.BeforeEach; + import org.junit.jupiter.api.Test; import java.util.Arrays; From 62e62d46a66b5aa896c863454a6f1c7a135ebf14 Mon Sep 17 00:00:00 2001 From: angelicalin Date: Fri, 9 Feb 2018 14:31:44 -0600 Subject: [PATCH 2/2] finish homework --- .../inspectionProfiles/Project_Default.xml | 21 ---- java-type-checker/.idea/misc.xml | 2 +- java-type-checker/.idea/type-checker.iml | 2 +- .../java_type_checker/expressions.py | 106 +++++++++++++++++- java-type-checker/java_type_checker/types.py | 12 +- java-type-checker/tests/test_null.py | 5 +- java-type-checker/tests/test_static_types.py | 4 +- java-type-checker/tests/test_type_checking.py | 32 ++---- 8 files changed, 125 insertions(+), 59 deletions(-) delete mode 100644 java-type-checker/.idea/inspectionProfiles/Project_Default.xml diff --git a/java-type-checker/.idea/inspectionProfiles/Project_Default.xml b/java-type-checker/.idea/inspectionProfiles/Project_Default.xml deleted file mode 100644 index b169286..0000000 --- a/java-type-checker/.idea/inspectionProfiles/Project_Default.xml +++ /dev/null @@ -1,21 +0,0 @@ - - - - \ No newline at end of file diff --git a/java-type-checker/.idea/misc.xml b/java-type-checker/.idea/misc.xml index c24fcb0..0535679 100644 --- a/java-type-checker/.idea/misc.xml +++ b/java-type-checker/.idea/misc.xml @@ -12,5 +12,5 @@ - + \ No newline at end of file diff --git a/java-type-checker/.idea/type-checker.iml b/java-type-checker/.idea/type-checker.iml index 52e75c6..53835e7 100644 --- a/java-type-checker/.idea/type-checker.iml +++ b/java-type-checker/.idea/type-checker.iml @@ -2,7 +2,7 @@ - + diff --git a/java-type-checker/java_type_checker/expressions.py b/java-type-checker/java_type_checker/expressions.py index 27ed57e..eb330c3 100644 --- a/java-type-checker/java_type_checker/expressions.py +++ b/java-type-checker/java_type_checker/expressions.py @@ -14,14 +14,17 @@ def static_type(self): Returns the compile-time type of this expression, i.e. the most specific type that describes all the possible values it could take on at runtime. Subclasses must implement this method. """ - raise NotImplementedError(type(self).__name__ + " must implement static_type()") + # raise NotImplementedError(type(self).__name__ + " must implement static_type()") + + return Expression + def check_types(self): """ Validates the structure of this expression, checking for any logical inconsistencies in the child nodes and the operation this expression applies to them. """ - raise NotImplementedError(type(self).__name__ + " must implement check_types()") + class Variable(Expression): @@ -30,7 +33,8 @@ class Variable(Expression): def __init__(self, name, declared_type): self.name = name #: The name of the variable self.declared_type = declared_type #: The declared type of the variable (Type) - + def static_type(self): + return self.declared_type class Literal(Expression): """ A literal value entered in the code, e.g. `5` in the expression `x + 5`. @@ -39,11 +43,14 @@ def __init__(self, value, type): self.value = value #: The literal value, as a string self.type = type #: The type of the literal (Type) + def static_type(self): + return self.type class NullLiteral(Literal): def __init__(self): super().__init__("null", Type.null) - + def static_type(self): + return self.type class MethodCall(Expression): """ @@ -55,6 +62,57 @@ def __init__(self, receiver, method_name, *args): self.method_name = method_name #: The name of the method to call (String) self.args = args #: The method arguments (list of Expressions) + def static_type(self): + return self.receiver.static_type().method_named(self.method_name).return_type + + def check_types(self): + #if the reciever is null + try: + self.static_type() + pass + except AttributeError: + pass + + #check if the receiver is instantiable + if not self.receiver.static_type().is_instantiable: + raise JavaTypeError("Type {0} does not have methods".format(self.receiver.static_type().name)) + + #check for wrong number of arguments + if len(self.args) != len(self.receiver.static_type().method_named(self.method_name).argument_types): + raise JavaTypeError( + "Wrong number of arguments for {3}.{0}(): expected {1}, got {2}".format( + self.method_name, len(self.receiver.static_type().method_named(self.method_name).argument_types), + len(self.args),self.receiver.static_type().name)) + + + #check for wrong type of arguments + argList = [] + for arg in self.args: + argList += [arg.static_type()] + consList = [] + for constype in self.receiver.static_type().method_named(self.method_name).argument_types: + consList += [constype] + for i in range(len(self.args)): + if hasattr(self.args[i],"args"): + self.args[i].check_types() + if ( not argList[i].is_subtype_of(consList[i])) and (argList[i] is not Type.null): + raise JavaTypeError( + "{0}.{1}() expects arguments of type {2}, but got {3}".format( + self.receiver.static_type().name, self.method_name, names(consList), names(argList) + ) + ) + if (not consList[i].is_subtype_of([Type.object])): + print(consList[i].name) + if (( not consList[i].is_instantiable) and (argList[i] is Type.null)): + raise JavaTypeError( + "{0}.{1}() expects arguments of type {2}, but got {3}".format( + self.receiver.static_type().name, self.method_name, names(consList), names(argList) + ) + ) + + + + class ConstructorCall(Expression): """ @@ -63,6 +121,46 @@ class ConstructorCall(Expression): def __init__(self, instantiated_type, *args): self.instantiated_type = instantiated_type #: The type to instantiate (Type) self.args = args #: Constructor arguments (list of Expressions) + def static_type(self): + return self.instantiated_type + def check_types(self): + #Check if primitive + if not self.instantiated_type.is_instantiable: + raise JavaTypeError("Type {0} is not instantiable".format(self.instantiated_type.name)) + + #Wrong number of constructor args + if len(self.args) != len(self.static_type().constructor.argument_types): + raise JavaTypeError( + "Wrong number of arguments for {0} constructor: expected {1}, got {2}".format( + self.static_type().name, + len(self.static_type().constructor.argument_types), + len(self.args))) + #wrong type of construct + argList = [] + for arg in self.args: + argList += [arg.static_type()] + consList = [] + for cons in self.static_type().constructor.argument_types: + consList += [cons] + for i in range(len(self.args)): + if hasattr(self.args[i],"args"): + self.args[i].check_types() + + + + if (not argList[i].is_subtype_of(consList[i])) and (argList[i] is not Type.null) : + raise JavaTypeError( + "{0} constructor expects arguments of type {1}, but got {2}".format( + self.static_type().name, names(consList),names(argList) + ) + ) + if (not consList[i].is_instantiable) and (argList[i] is Type.null): + raise JavaTypeError( + "{0} constructor expects arguments of type {1}, but got {2}".format( + self.static_type().name, names(consList), names(argList) + ) + ) + class JavaTypeError(Exception): diff --git a/java-type-checker/java_type_checker/types.py b/java-type-checker/java_type_checker/types.py index 465f7f4..813c1de 100644 --- a/java-type-checker/java_type_checker/types.py +++ b/java-type-checker/java_type_checker/types.py @@ -12,7 +12,11 @@ def __init__(self, name, direct_supertypes=[]): def is_subtype_of(self, other): """ True if this type can be used where the other type is expected. """ - return True # TODO: implement + if (other == self) or (other in self.direct_supertypes): + return True + else: + for item in self.direct_supertypes: + return False or item.is_subtype_of(other) def is_supertype_of(self, other): """ Convenience counterpart to is_subtype_of(). @@ -23,13 +27,16 @@ def is_supertype_of(self, other): class Constructor(object): """ The declaration of a Java constructor. """ + is_runnable = True def __init__(self, argument_types=[]): self.argument_types = argument_types + class Method(object): """ The declaration of a Java method. """ + is_runnable = True def __init__(self, name, argument_types=[], return_type=None): self.name = name self.argument_types = argument_types @@ -71,6 +78,9 @@ class NullType(Type): """ def __init__(self): super().__init__("null") + self.is_instantiable=False + def method_named(self,name): + raise NoSuchMethod("Cannot invoke method {0}() on null".format(name)) class NoSuchMethod(Exception): diff --git a/java-type-checker/tests/test_null.py b/java-type-checker/tests/test_null.py index 36693c2..b5b8d2c 100644 --- a/java-type-checker/tests/test_null.py +++ b/java-type-checker/tests/test_null.py @@ -75,10 +75,7 @@ def test_passes_deep_expression(self): MethodCall( Variable("group", Graphics.graphics_group), "add", - ConstructorCall( - Graphics.rectangle, - NullLiteral(), - NullLiteral()))) + ConstructorCall(Graphics.rectangle,NullLiteral(),NullLiteral()))) def test_catch_wrong_type_in_deep_expression(self): """ diff --git a/java-type-checker/tests/test_static_types.py b/java-type-checker/tests/test_static_types.py index fcedb26..61cd7f6 100755 --- a/java-type-checker/tests/test_static_types.py +++ b/java-type-checker/tests/test_static_types.py @@ -25,9 +25,7 @@ def test_null_literal_static_type_is_null(self): def test_method_call_static_type_is_method_return_type(self): # p.getX() → double - self.assertEqual( - Type.double, - MethodCall(Variable("p", Graphics.point), "getX").static_type()) + self.assertEqual(Type.double, MethodCall(Variable("p", Graphics.point), "getX").static_type()) def test_object_instantiation_static_type_is_the_instantiate_type(self): # new Point() → Point diff --git a/java-type-checker/tests/test_type_checking.py b/java-type-checker/tests/test_type_checking.py index b10ef24..9915f82 100644 --- a/java-type-checker/tests/test_type_checking.py +++ b/java-type-checker/tests/test_type_checking.py @@ -56,10 +56,7 @@ def test_flags_too_many_arguments(self): JavaTypeError, "Wrong number of arguments for Point.getX(): expected 0, got 2", MethodCall( - Variable("p", Graphics.point), - "getX", - Literal("0.0", Type.double), - Literal("1.0", Type.double))) + Variable("p", Graphics.point),"getX",Literal("0.0", Type.double),Literal("1.0", Type.double))) def test_flags_too_few_arguments(self): """ @@ -135,10 +132,7 @@ def test_flags_wrong_constructor_argument_type(self): self.assertCompileError( JavaTypeError, "Rectangle constructor expects arguments of type (Point, Size), but got (Point, boolean)", - ConstructorCall( - Graphics.rectangle, - Variable("p", Graphics.point), - Literal("true", Type.boolean))) + ConstructorCall(Graphics.rectangle, Variable("p", Graphics.point), Literal("true", Type.boolean))) def test_cannot_call_methods_on_primitives(self): """ @@ -148,8 +142,7 @@ def test_cannot_call_methods_on_primitives(self): x.hashCode() """ - self.assertCompileError( - JavaTypeError, + self.assertCompileError(JavaTypeError, "Type int does not have methods", MethodCall( Variable("x", Type.int), @@ -177,17 +170,12 @@ def test_does_not_allow_void_passed_as_argument(self): rect.setFillColor( // error here rect.setStrokeColor(red)); // returns void """ - self.assertCompileError( - JavaTypeError, - "Rectangle.setFillColor() expects arguments of type (Paint), but got (void)", - MethodCall( - Variable("rect", Graphics.rectangle), - "setFillColor", - MethodCall( - Variable("rect", Graphics.rectangle), - "setStrokeColor", + self.assertCompileError(JavaTypeError,"Rectangle.setFillColor() expects arguments of type (Paint), but got (void)", + MethodCall(Variable("rect", Graphics.rectangle),"setFillColor", + MethodCall(Variable("rect", Graphics.rectangle),"setStrokeColor", Variable("red", Graphics.color)))) + def test_passes_deep_expression(self): """ Equivalent Java: @@ -231,11 +219,7 @@ def test_catch_wrong_name_in_deep_expression(self): MethodCall( Variable("group", Graphics.graphics_group), "add", - ConstructorCall( - Graphics.rectangle, - ConstructorCall(Graphics.point, - Literal("0.0", Type.double), - Literal("0.0", Type.double)), + ConstructorCall(Graphics.rectangle, ConstructorCall(Graphics.point,Literal("0.0", Type.double),Literal("0.0", Type.double)), MethodCall( Variable("window", Graphics.window), "getFunky"))))