From b4594150c870405ee78acb3f8440182111d96c84 Mon Sep 17 00:00:00 2001 From: Tara Date: Thu, 8 Feb 2018 23:50:28 -0600 Subject: [PATCH 1/4] Added JUinit --- python-attr-lookup/python-attr-lookup.iml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/python-attr-lookup/python-attr-lookup.iml b/python-attr-lookup/python-attr-lookup.iml index 01e8e1b..a2b4cff 100644 --- a/python-attr-lookup/python-attr-lookup.iml +++ b/python-attr-lookup/python-attr-lookup.iml @@ -20,5 +20,17 @@ + + + + + + + + + + + + \ No newline at end of file From 652bcb0775cedca17d8589d4da759453b4a71b0f Mon Sep 17 00:00:00 2001 From: Tara Date: Thu, 8 Feb 2018 23:50:39 -0600 Subject: [PATCH 2/4] Added tests from master --- python-attr-lookup/test/plang/PythonObjectTest.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/python-attr-lookup/test/plang/PythonObjectTest.java b/python-attr-lookup/test/plang/PythonObjectTest.java index 9fa0483..71316fa 100644 --- a/python-attr-lookup/test/plang/PythonObjectTest.java +++ b/python-attr-lookup/test/plang/PythonObjectTest.java @@ -38,6 +38,9 @@ void createTestTypeHierarchy() { @Test void canCreateAndInstantiateTypes() { // do nothing; we’re just making sure the @BeforeEach block above succeeded + assertSame(fooType, foo.getType()); + assertSame(barType, bar.getType()); + assertNotSame(foo, bar); } // –––––– MRO tests –––––– From 4d3d33e65e406043919b9d6c17edde67b6c42cc3 Mon Sep 17 00:00:00 2001 From: Tara Date: Thu, 8 Feb 2018 23:51:04 -0600 Subject: [PATCH 3/4] Implemented python objects in java! --- python-attr-lookup/src/plang/PythonObject.java | 15 ++++++++++++--- python-attr-lookup/src/plang/PythonType.java | 9 +++++++-- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/python-attr-lookup/src/plang/PythonObject.java b/python-attr-lookup/src/plang/PythonObject.java index a8e311f..f1bd907 100644 --- a/python-attr-lookup/src/plang/PythonObject.java +++ b/python-attr-lookup/src/plang/PythonObject.java @@ -51,7 +51,11 @@ 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"); + ArrayList temp = new ArrayList<>(); + temp.add(this); + if(type != null) + temp.addAll(type.getMRO()); + return temp; } /** @@ -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 pyob : getMRO()){ + if(pyob.attrs.containsKey(attrName)){ + return pyob.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..f332796 100644 --- a/python-attr-lookup/src/plang/PythonType.java +++ b/python-attr-lookup/src/plang/PythonType.java @@ -41,7 +41,11 @@ public PythonObject getBase() { @Override protected List buildMRO() { - throw new UnsupportedOperationException("not implemented yet"); + ArrayList temp = new ArrayList<>(); + temp.add(this); + if(base != null) + temp.addAll(base.getMRO()); + return temp; } /** @@ -49,7 +53,8 @@ protected List buildMRO() { * this PythonType. */ public PythonObject instantiate() { - throw new UnsupportedOperationException("not implemented yet"); + return new PythonObject(this); + //throw new UnsupportedOperationException("not implemented yet"); } @Override From 0813dcd4fde401deb78b164f1d1f0a4ddd7dd717 Mon Sep 17 00:00:00 2001 From: Tara Date: Fri, 9 Feb 2018 01:57:00 -0600 Subject: [PATCH 4/4] Implimented Java typechecking in Python --- .../java_type_checker/expressions.py | 77 +++++++++++++++++++ java-type-checker/java_type_checker/types.py | 16 +++- 2 files changed, 92 insertions(+), 1 deletion(-) diff --git a/java-type-checker/java_type_checker/expressions.py b/java-type-checker/java_type_checker/expressions.py index 27ed57e..3c28acd 100644 --- a/java-type-checker/java_type_checker/expressions.py +++ b/java-type-checker/java_type_checker/expressions.py @@ -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,11 +45,23 @@ 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): """ @@ -55,6 +73,32 @@ 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 not self.receiver.static_type().is_subtype_of(Type.object): + raise JavaTypeError( + "Type {0} does not have methods".format(self.receiver.static_type().name)) + + target_args = self.receiver.static_type().method_named(self.method_name).argument_types + if len(target_args) != len(self.args): + raise JavaTypeError( + "Wrong number of arguments for {0}: expected {1}, got {2}".format( + self.receiver.static_type().name + "." + self.method_name + "()", + len(target_args), + len(self.args))) + + for i, arg in enumerate(self.args): + arg.check_types() + if not (arg.static_type().is_subtype_of(target_args[i])): + raise JavaTypeError( + "{0} expects arguments of type {1}, but got {2}".format( + self.receiver.static_type().name + "." + self.method_name + "()", + names(target_args), + types(self.args))) + class ConstructorCall(Expression): """ @@ -64,6 +108,33 @@ 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): + if not self.instantiated_type.is_subtype_of(Type.object): + raise JavaTypeError( + "Type {0} is not instantiable".format(self.instantiated_type.name)) + if self.instantiated_type == Type.null: + raise JavaTypeError( + "Type null is not instantiable") + + target_args = self.instantiated_type.constructor.argument_types + if len(target_args) != len(self.args): + raise JavaTypeError( + "Wrong number of arguments for {0} constructor: expected {1}, got {2}".format( + self.instantiated_type.name, + len(target_args), + len(self.args))) + for i, arg in enumerate(self.args): + arg.check_types() + if not (arg.static_type().is_subtype_of(target_args[i])): + raise JavaTypeError( + "{0} constructor expects arguments of type {1}, but got {2}".format( + self.instantiated_type.name, + names(target_args), + types(self.args))) + class JavaTypeError(Exception): """ Indicates a compile-time type error in an expression. @@ -75,3 +146,9 @@ def names(named_things): """ Helper for formatting pretty error messages """ return "(" + ", ".join([e.name for e in named_things]) + ")" + + +def types(typed_things): + """ Helper for formatting pretty error messages + """ + return "(" + ", ".join([e.static_type().name for e in typed_things]) + ")" diff --git a/java-type-checker/java_type_checker/types.py b/java-type-checker/java_type_checker/types.py index 465f7f4..dd0b90c 100644 --- a/java-type-checker/java_type_checker/types.py +++ b/java-type-checker/java_type_checker/types.py @@ -12,7 +12,12 @@ 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 self.name == other.name: + return True + for supertype in self.direct_supertypes: + if supertype.is_subtype_of(other): + return True + return False def is_supertype_of(self, other): """ Convenience counterpart to is_subtype_of(). @@ -72,6 +77,15 @@ class NullType(Type): def __init__(self): super().__init__("null") + def is_subtype_of(self, other): + return other.is_subtype_of(Type.object) + + def method_named(self, name): + """ Returns the Method with the given name, which may come from a supertype. + """ + raise NoSuchMethod("Cannot invoke method {0}() on null".format(name)) + + class NoSuchMethod(Exception): pass