diff --git a/src/main/java/com/annimon/ownlang/lib/ClassDeclarations.java b/src/main/java/com/annimon/ownlang/lib/ClassDeclarations.java index 1335b1b..b079ef3 100644 --- a/src/main/java/com/annimon/ownlang/lib/ClassDeclarations.java +++ b/src/main/java/com/annimon/ownlang/lib/ClassDeclarations.java @@ -1,15 +1,14 @@ package com.annimon.ownlang.lib; -import com.annimon.ownlang.exceptions.UnknownFunctionException; import com.annimon.ownlang.parser.ast.ClassDeclarationStatement; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public final class ClassDeclarations { private static final Map declarations; static { - declarations = new HashMap<>(); + declarations = new ConcurrentHashMap<>(); } private ClassDeclarations() { } @@ -22,12 +21,7 @@ public final class ClassDeclarations { return declarations; } - public static boolean isExists(String key) { - return declarations.containsKey(key); - } - public static ClassDeclarationStatement get(String key) { - if (!isExists(key)) throw new UnknownFunctionException(key); return declarations.get(key); } diff --git a/src/main/java/com/annimon/ownlang/lib/Instantiable.java b/src/main/java/com/annimon/ownlang/lib/Instantiable.java new file mode 100644 index 0000000..709b4c7 --- /dev/null +++ b/src/main/java/com/annimon/ownlang/lib/Instantiable.java @@ -0,0 +1,9 @@ +package com.annimon.ownlang.lib; + +/** + * Interface for values that supports creating instances with `new` keyword. + */ +public interface Instantiable { + + Value newInstance(Value[] args); +} diff --git a/src/main/java/com/annimon/ownlang/modules/java/java.java b/src/main/java/com/annimon/ownlang/modules/java/java.java index c8f7822..58ef5fc 100644 --- a/src/main/java/com/annimon/ownlang/modules/java/java.java +++ b/src/main/java/com/annimon/ownlang/modules/java/java.java @@ -103,7 +103,7 @@ public final class java implements Module { } } - private static class ClassValue extends MapValue { + private static class ClassValue extends MapValue implements Instantiable { public static Value classOrNull(Class clazz) { if (clazz == null) return NULL; @@ -162,7 +162,8 @@ public final class java implements Module { return NumberValue.fromBoolean(clazz.isAssignableFrom( ((ClassValue)args[0]).clazz )); } - private Value newInstance(Value[] args) { + @Override + public Value newInstance(Value[] args) { return findConstructorAndInstantiate(args, clazz.getConstructors()); } diff --git a/src/main/java/com/annimon/ownlang/parser/ast/ObjectCreationExpression.java b/src/main/java/com/annimon/ownlang/parser/ast/ObjectCreationExpression.java index e5edc27..6e15ad0 100644 --- a/src/main/java/com/annimon/ownlang/parser/ast/ObjectCreationExpression.java +++ b/src/main/java/com/annimon/ownlang/parser/ast/ObjectCreationExpression.java @@ -1,5 +1,6 @@ package com.annimon.ownlang.parser.ast; +import com.annimon.ownlang.exceptions.UnknownClassException; import com.annimon.ownlang.lib.*; import java.util.Iterator; import java.util.List; @@ -17,6 +18,16 @@ public final class ObjectCreationExpression implements Expression { @Override public Value eval() { final ClassDeclarationStatement cd = ClassDeclarations.get(className); + if (cd == null) { + // Is Instantiable? + if (Variables.isExists(className)) { + final Value variable = Variables.get(className); + if (variable instanceof Instantiable) { + return ((Instantiable) variable).newInstance(ctorArgs()); + } + } + throw new UnknownClassException(className); + } // Create an instance and put evaluated fields with method declarations final ClassInstanceValue instance = new ClassInstanceValue(className); @@ -30,14 +41,17 @@ public final class ObjectCreationExpression implements Expression { } // Call a constructor + instance.callConstructor(ctorArgs()); + return instance; + } + + private Value[] ctorArgs() { final int argsSize = constructorArguments.size(); final Value[] ctorArgs = new Value[argsSize]; for (int i = 0; i < argsSize; i++) { ctorArgs[i] = constructorArguments.get(i).eval(); } - instance.callConstructor(ctorArgs); - - return instance; + return ctorArgs; } @Override