diff --git a/java-type-checker/.idea/misc.xml b/java-type-checker/.idea/misc.xml index c24fcb0..a7ce7ea 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..abd342a 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..9a494e7 100644 --- a/java-type-checker/java_type_checker/expressions.py +++ b/java-type-checker/java_type_checker/expressions.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from .types import Type +from .types import Type, NoSuchMethod class Expression(object): @@ -31,6 +31,12 @@ 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 + + def check_types(self): + pass + class Literal(Expression): """ A literal value entered in the code, e.g. `5` in the expression `x + 5`. @@ -39,22 +45,69 @@ 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 + + def check_types(self): + pass + + class NullLiteral(Literal): def __init__(self): super().__init__("null", Type.null) + def static_type(self): + return Type.null + + def check_types(self): + pass + class MethodCall(Expression): """ A Java method invocation, i.e. `foo.bar(0, 1, 2)`. """ def __init__(self, receiver, method_name, *args): - self.receiver = receiver self.receiver = receiver #: The object whose method we are calling (Expression) 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): + #check for the primitive error + if not self.receiver.static_type().is_instantiable: + raise JavaTypeError( + "Type {0} does not have methods".format( + self.receiver.static_type().name)) + + method = self.receiver.static_type().method_named(self.method_name) + expected_argument_types = method.argument_types + numOfMethodParameters = len(method.argument_types) + + + #If the length of methods are not the same + if (len(self.args) != numOfMethodParameters): + raise JavaTypeError( + "Wrong number of arguments for {0}: expected {1}, got {2}".format( + str(self.receiver.static_type().name) + "." + str(self.method_name) + "()", + numOfMethodParameters, + len(self.args))) + + actual_argument_types = [] + for i in range(len(self.args)): + actual_argument_types.append(self.args[i].static_type()) + + for i in range(len(expected_argument_types)): + if not actual_argument_types[i].is_subtype_of(expected_argument_types[i]): + raise JavaTypeError( + "{0} expects arguments of type {1}, but got {2}".format( + str(self.receiver.static_type().name) + "." + str(self.method_name) + "()", + names(expected_argument_types), + names(actual_argument_types))) + class ConstructorCall(Expression): """ @@ -64,6 +117,38 @@ 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): + #checking if it is the primitives types. + if not(self.instantiated_type.is_instantiable): + raise JavaTypeError( + "Type {0} is not instantiable".format( + self.instantiated_type.name)) + + list_of_expected_constructor_arguments = self.instantiated_type.constructor.argument_types + + if (len(self.args) != len(list_of_expected_constructor_arguments)): + raise JavaTypeError( + "Wrong number of arguments for {0} constructor: expected {1}, got {2}".format( + self.instantiated_type.name, + len(list_of_expected_constructor_arguments), + len(self.args) + ) + ) + + list_of_actual_argument_types = [] + for i in range(len(self.args)): + list_of_actual_argument_types.append(self.args[i].static_type()) + + for i in range(len(list_of_expected_constructor_arguments)): + if not list_of_actual_argument_types[i].is_subtype_of(list_of_expected_constructor_arguments[i]): + raise JavaTypeError( + "{0} constructor expects arguments of type {1}, but got {2}".format( + self.instantiated_type.name, + names(list_of_expected_constructor_arguments), + names(list_of_actual_argument_types))) class JavaTypeError(Exception): """ Indicates a compile-time type error in an expression. diff --git a/java-type-checker/java_type_checker/types.py b/java-type-checker/java_type_checker/types.py index 465f7f4..d72c5df 100644 --- a/java-type-checker/java_type_checker/types.py +++ b/java-type-checker/java_type_checker/types.py @@ -12,7 +12,13 @@ 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 is self): + return True + else: + for directsupertypes in self.direct_supertypes: + if (directsupertypes.is_subtype_of(other)): + return True + return False def is_supertype_of(self, other): """ Convenience counterpart to is_subtype_of(). @@ -71,7 +77,7 @@ class NullType(Type): """ def __init__(self): super().__init__("null") - + self.is_instantiable = False class NoSuchMethod(Exception): pass diff --git a/java-type-checker/tests/test_null.py b/java-type-checker/tests/test_null.py index 36693c2..6de11cb 100644 --- a/java-type-checker/tests/test_null.py +++ b/java-type-checker/tests/test_null.py @@ -13,7 +13,7 @@ def test_object_params_accept_null(self): Equivalent Java: Rectangle rect; - +https://github.com/khintk/comp394-type-modeling rect.setFillColor(null); """ self.assertNoCompileErrors( @@ -22,6 +22,7 @@ def test_object_params_accept_null(self): "setFillColor", NullLiteral())) + def test_cannot_call_method_on_null(self): """ Equivalent Java: diff --git a/java-type-checker/tests/test_type_checking.py b/java-type-checker/tests/test_type_checking.py index b10ef24..d544433 100644 --- a/java-type-checker/tests/test_type_checking.py +++ b/java-type-checker/tests/test_type_checking.py @@ -8,15 +8,15 @@ class TestTypeChecking(TypeTest): - def test_variables_never_have_type_errors(self): + def test_variables_never_have_type_errors(self): #Pass self.assertNoCompileErrors( Variable("p", Graphics.point)) - def test_literals_never_have_type_errors(self): + def test_literals_never_have_type_errors(self): #Pass self.assertNoCompileErrors( Variable("3.72", Type.double)) - def test_simple_method_call_passes(self): + def test_simple_method_call_passes(self): #pass """ Equivalent Java: @@ -29,7 +29,7 @@ def test_simple_method_call_passes(self): Variable("p", Graphics.point), "getX")) - def test_flags_nonexistent_method(self): + def test_flags_nonexistent_method(self): #Pass """ Equivalent Java: @@ -44,7 +44,7 @@ def test_flags_nonexistent_method(self): Variable("p", Graphics.point), "getZ")) - def test_flags_too_many_arguments(self): + def test_flags_too_many_arguments(self): #Pass """ Equivalent Java: @@ -61,7 +61,7 @@ def test_flags_too_many_arguments(self): Literal("0.0", Type.double), Literal("1.0", Type.double))) - def test_flags_too_few_arguments(self): + def test_flags_too_few_arguments(self): #Pass """ Equivalent Java: @@ -77,7 +77,7 @@ def test_flags_too_few_arguments(self): "setPosition", Literal("0.0", Type.double))) - def test_flags_wrong_argument_type(self): + def test_flags_wrong_argument_type(self): #Pass """ Equivalent Java: @@ -94,7 +94,7 @@ def test_flags_wrong_argument_type(self): Literal("0.0", Type.double), Literal("true", Type.boolean))) - def test_allows_subtypes_for_arguments(self): + def test_allows_subtypes_for_arguments(self): #Pass """ Equivalent Java: @@ -109,7 +109,7 @@ def test_allows_subtypes_for_arguments(self): "setFillColor", Variable("red", Graphics.color))) - def test_flags_wrong_number_of_constructor_arguments(self): + def test_flags_wrong_number_of_constructor_arguments(self): #Pass """ Equivalent Java: @@ -124,7 +124,7 @@ def test_flags_wrong_number_of_constructor_arguments(self): Graphics.rectangle, Variable("p", Graphics.point))) - def test_flags_wrong_constructor_argument_type(self): + def test_flags_wrong_constructor_argument_type(self): #Fail """ Equivalent Java: @@ -140,7 +140,7 @@ def test_flags_wrong_constructor_argument_type(self): Variable("p", Graphics.point), Literal("true", Type.boolean))) - def test_cannot_call_methods_on_primitives(self): + def test_cannot_call_methods_on_primitives(self): # Pass """ Equivalent Java: @@ -160,14 +160,14 @@ def test_cannot_call_methods_on_primitives(self): new int() """ - def test_cannot_instantiate_primitives(self): + def test_cannot_instantiate_primitives(self): #Pass self.assertCompileError( JavaTypeError, "Type int is not instantiable", ConstructorCall( Type.int)) - def test_does_not_allow_void_passed_as_argument(self): + def test_does_not_allow_void_passed_as_argument(self): #Fail """ Equivalent Java: @@ -188,7 +188,7 @@ def test_does_not_allow_void_passed_as_argument(self): "setStrokeColor", Variable("red", Graphics.color)))) - def test_passes_deep_expression(self): + def test_passes_deep_expression(self): #Fail """ Equivalent Java: @@ -213,7 +213,7 @@ def test_passes_deep_expression(self): Variable("window", Graphics.window), "getSize")))) - def test_catch_wrong_name_in_deep_expression(self): + def test_catch_wrong_name_in_deep_expression(self): #Fail """ Equivalent Java: diff --git a/python-attr-lookup/python-attr-lookup.iml b/python-attr-lookup/python-attr-lookup.iml index 01e8e1b..c514cf2 100644 --- a/python-attr-lookup/python-attr-lookup.iml +++ b/python-attr-lookup/python-attr-lookup.iml @@ -9,12 +9,10 @@ - + - - - - + + diff --git a/python-attr-lookup/src/plang/PythonObject.java b/python-attr-lookup/src/plang/PythonObject.java index a8e311f..321bb27 100644 --- a/python-attr-lookup/src/plang/PythonObject.java +++ b/python-attr-lookup/src/plang/PythonObject.java @@ -1,10 +1,6 @@ package plang; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * The runtime state of an object in Python. @@ -51,7 +47,10 @@ public List getMRO() { * result (i.e. it remembers the list buildMRO() returned and keeps returning it). */ protected List buildMRO() { - throw new UnsupportedOperationException("not implemented yet"); + List resultMRO = new ArrayList<>(); + resultMRO.add(this); //adding the self + resultMRO.addAll(this.getType().getMRO()); //adding the subclasses + return resultMRO; } /** @@ -62,8 +61,16 @@ 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"); - } + + List mroresults = getMRO(); + for (int i = 0; i < mroresults.size(); i++) { + if (mroresults.get(i).attrs.containsKey(attrName)) { + return mroresults.get(i).attrs.get(attrName); + } + } + throw new PythonAttributeException(this, attrName); + } + /** * Add or changes the value of an attribute on this object. Note that it sets the value for @@ -73,8 +80,9 @@ public final PythonObject get(String attrName) throws PythonAttributeException { * @param attrName The name of the attribute to set * @param value Its new value */ + public final void set(String attrName, PythonObject value) { - throw new UnsupportedOperationException("not implemented yet"); + this.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..35b981e 100644 --- a/python-attr-lookup/src/plang/PythonType.java +++ b/python-attr-lookup/src/plang/PythonType.java @@ -19,6 +19,7 @@ public class PythonType extends PythonObject { * (In real Python, instead of null it would be the class called `object`, and * it would be a list instead of a single value.) */ + public PythonType(String name, PythonObject base) { super(null); // In real Python, this would be the type called `type` this.name = name; @@ -29,6 +30,7 @@ public PythonType(String name, PythonObject base) { * The name of this class. */ public String getName() { + return name; } @@ -36,12 +38,18 @@ public String getName() { * The base type (superclass) of this class. */ public PythonObject getBase() { + return base; } @Override protected List buildMRO() { - throw new UnsupportedOperationException("not implemented yet"); + List resultMRO = new ArrayList<>(); + resultMRO.add(this); + if (this.getBase() != null){ + resultMRO.addAll(this.getBase().getMRO()); + } + return resultMRO; } /** @@ -49,7 +57,8 @@ protected List buildMRO() { * this PythonType. */ public PythonObject instantiate() { - throw new UnsupportedOperationException("not implemented yet"); + PythonObject instance = new PythonObject(this); + return instance; } @Override diff --git a/python-attr-lookup/test/plang/PythonObjectTest.java b/python-attr-lookup/test/plang/PythonObjectTest.java index 9fa0483..d813030 100644 --- a/python-attr-lookup/test/plang/PythonObjectTest.java +++ b/python-attr-lookup/test/plang/PythonObjectTest.java @@ -8,13 +8,13 @@ import static org.junit.jupiter.api.Assertions.*; + class PythonObjectTest { private PythonType fooType; private PythonType barType; private PythonObject foo; private PythonObject bar; - /** * Equivalent Python: * @@ -100,7 +100,7 @@ void objectsSupportNullValues() throws Exception { assertEquals(null, foo.get("worries")); // No exception! } - @Test + @Test //didnt pass void findInheritedAttrs() throws Exception { // Equivalent Python: // @@ -116,7 +116,7 @@ void findInheritedAttrs() throws Exception { assertEqualsPyStr("rainbow", bar.get("socks")); } - @Test + @Test //didnt pass void overrideInheritedAttrsInType() throws Exception { // Equivalent Python: // @@ -132,7 +132,7 @@ void overrideInheritedAttrsInType() throws Exception { assertEqualsPyStr("polka dot", bar.get("socks")); } - @Test + @Test //didnt pass void overrideInheritedAttrsInInstance() throws Exception { // Equivalent Python: // @@ -149,7 +149,7 @@ void overrideInheritedAttrsInInstance() throws Exception { } - @Test + @Test //didnt pass void overrideInheritedAttrsWithNull() throws Exception { // Equivalent Python: //