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