diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..9e911f7 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +comp394-type-modeling \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..9a8b7e5 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..97626ba --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..d5d79e0 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..1ccf35d --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file 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..267cb20 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..c8a7e47 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..fd8861e 100644 --- a/java-type-checker/java_type_checker/expressions.py +++ b/java-type-checker/java_type_checker/expressions.py @@ -31,6 +31,11 @@ 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): + return class Literal(Expression): """ A literal value entered in the code, e.g. `5` in the expression `x + 5`. @@ -39,11 +44,19 @@ 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): + return class NullLiteral(Literal): def __init__(self): super().__init__("null", Type.null) + self.declared_type = Type.null + def static_type(self): + return Type.null class MethodCall(Expression): """ @@ -55,6 +68,38 @@ 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): + classtype = self.receiver.declared_type + method = classtype.method_named(self.method_name) + return(method.return_type) + + def check_types(self): + classtype = self.receiver.declared_type + + if classtype.is_subtype_of(Type.boolean) or classtype.is_subtype_of(Type.int) or classtype.is_subtype_of(Type.double): + raise JavaTypeError("Type {0} does not have methods".format(classtype.name)) + + method = classtype.method_named(self.method_name) + argsExpected = method.argument_types #not certain what type this is. + args = self.args #But these are definitely expressions + typesGot = [] + + for arg in args: + typesGot.append(arg.static_type()) + arg.check_types() + + + if(len(argsExpected) != len(args)): + raise JavaTypeError("Wrong number of arguments for {3}.{0}(): expected {1}, got {2}".format(self.method_name, len(argsExpected), len(args), classtype.name)) + + for i in range(len(args)): + typeExp = argsExpected[i] + expressionGot = args[i] + expressionGot.check_types() + typeGot = expressionGot.static_type() + if (not typeGot.is_subtype_of(typeExp)) and typesGot != argsExpected: + raise JavaTypeError("{0}.{1}() expects arguments of type {2}, but got {3}".format(classtype.name, self.method_name, names(argsExpected), names(typesGot))) + return class ConstructorCall(Expression): """ @@ -65,6 +110,35 @@ def __init__(self, instantiated_type, *args): self.args = args #: Constructor arguments (list of Expressions) + + def static_type(self): + return self.instantiated_type + + def check_types(self): + classType = self.static_type() + if classType == Type.null: + raise JavaTypeError("Type null is not instantiable") + + if classType.is_subtype_of(Type.boolean) or classType.is_subtype_of(Type.int) or classType.is_subtype_of(Type.double): + raise JavaTypeError("Type {0} is not instantiable".format(classType.name)) + + argsGot = self.args + argsExp = classType.constructor.argument_types + typesGot = [] + for arg in argsGot: + typesGot.append(arg.static_type()) + arg.check_types() + + if(len(argsExp) != len(argsGot)): + raise JavaTypeError("Wrong number of arguments for {0} constructor: expected {1}, got {2}".format(classType.name, len(argsExp), len(argsGot))) + for i in range(len(argsGot)): + typeExp = argsExp[i] + typeGot = argsGot[i].static_type() + #second part checks for a weird edge case where Got (Point, Size) Expected (Point, Size) TODO: figure out why + if (not typeGot.is_subtype_of(typeExp)) and typesGot != argsExp: + raise JavaTypeError("{0} constructor expects arguments of type {1}, but got {2}".format(classType.name, names(argsExp), names(typesGot))) + return + 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..5c742f8 100644 --- a/java-type-checker/java_type_checker/types.py +++ b/java-type-checker/java_type_checker/types.py @@ -12,7 +12,20 @@ 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 + #Catch for self not in supertypes, modifies a copy of the direct_supertypes in case user didn't spec self in list + allSupers = [self] + prevSize = -1 + currentSize = 1 + while currentSize > prevSize: + prevSize = currentSize + for super in allSupers: + potentialNewSupers = super.direct_supertypes + for potentialSuper in potentialNewSupers: + if potentialSuper not in allSupers: + allSupers.append(potentialSuper) + currentSize+=1 + #Is this messy? yes it is. I'd rather use a set in this case but apparently returning arrays and then extending sets isn't viable + return(other in allSupers) def is_supertype_of(self, other): """ Convenience counterpart to is_subtype_of(). @@ -66,11 +79,26 @@ def method_named(self, name): raise NoSuchMethod("{0} has no method named {1}".format(self.name, name)) -class NullType(Type): +class NullType(ClassOrInterface): """ The type of the value `null` in Java. """ def __init__(self): super().__init__("null") + self.is_instantiable = False + self.methods = {} + + def method_named(self, name): + raise NoSuchMethod("Cannot invoke method {0}() on {1}".format(name, self.name)) + + def is_subtype_of(self, other): + #primitives can't be null + if(other.is_subtype_of(Type.boolean) or other.is_subtype_of(Type.int) or other.is_subtype_of(Type.double)): + return False + return True + + + + class NoSuchMethod(Exception): 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 diff --git a/python-attr-lookup/src/plang/PythonObject.java b/python-attr-lookup/src/plang/PythonObject.java index a8e311f..2ddc1a6 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"); + mro = new ArrayList<>(); + mro.add(this); + mro.addAll(this.getType().buildMRO()); + return mro; } /** @@ -62,7 +61,15 @@ 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"); + boolean foundVal = false; + List layers = getMRO(); + for(PythonObject layer : layers){ + if(layer.attrs.containsKey(attrName)) + return layer.attrs.get(attrName); + } + if(!foundVal) + throw new PythonAttributeException(this, attrName); + return null; } /** @@ -74,7 +81,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..19c10af 100644 --- a/python-attr-lookup/src/plang/PythonType.java +++ b/python-attr-lookup/src/plang/PythonType.java @@ -1,7 +1,6 @@ package plang; import java.util.ArrayList; -import java.util.Collections; import java.util.List; /** @@ -41,7 +40,12 @@ public PythonObject getBase() { @Override protected List buildMRO() { - throw new UnsupportedOperationException("not implemented yet"); + List mro = new ArrayList<>(); + mro.add(this); + if(this.base == null) + return mro; + mro.addAll(this.base.getMRO()); + return mro; } /** @@ -49,7 +53,9 @@ protected List buildMRO() { * this PythonType. */ public PythonObject instantiate() { - throw new UnsupportedOperationException("not implemented yet"); + return new PythonObject(this); + // todo: confirm this works? + //throw new UnsupportedOperationException("not implemented yet"); } @Override