Поддержка инстанцирования java-класса с помощью ключевого слова new

This commit is contained in:
Victor 2019-10-03 21:04:17 +03:00
parent 483c7c1242
commit 826891ac52
4 changed files with 31 additions and 13 deletions

View File

@ -1,15 +1,14 @@
package com.annimon.ownlang.lib; package com.annimon.ownlang.lib;
import com.annimon.ownlang.exceptions.UnknownFunctionException;
import com.annimon.ownlang.parser.ast.ClassDeclarationStatement; import com.annimon.ownlang.parser.ast.ClassDeclarationStatement;
import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public final class ClassDeclarations { public final class ClassDeclarations {
private static final Map<String, ClassDeclarationStatement> declarations; private static final Map<String, ClassDeclarationStatement> declarations;
static { static {
declarations = new HashMap<>(); declarations = new ConcurrentHashMap<>();
} }
private ClassDeclarations() { } private ClassDeclarations() { }
@ -22,12 +21,7 @@ public final class ClassDeclarations {
return declarations; return declarations;
} }
public static boolean isExists(String key) {
return declarations.containsKey(key);
}
public static ClassDeclarationStatement get(String key) { public static ClassDeclarationStatement get(String key) {
if (!isExists(key)) throw new UnknownFunctionException(key);
return declarations.get(key); return declarations.get(key);
} }

View File

@ -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);
}

View File

@ -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) { public static Value classOrNull(Class<?> clazz) {
if (clazz == null) return NULL; if (clazz == null) return NULL;
@ -162,7 +162,8 @@ public final class java implements Module {
return NumberValue.fromBoolean(clazz.isAssignableFrom( ((ClassValue)args[0]).clazz )); 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()); return findConstructorAndInstantiate(args, clazz.getConstructors());
} }

View File

@ -1,5 +1,6 @@
package com.annimon.ownlang.parser.ast; package com.annimon.ownlang.parser.ast;
import com.annimon.ownlang.exceptions.UnknownClassException;
import com.annimon.ownlang.lib.*; import com.annimon.ownlang.lib.*;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
@ -17,6 +18,16 @@ public final class ObjectCreationExpression implements Expression {
@Override @Override
public Value eval() { public Value eval() {
final ClassDeclarationStatement cd = ClassDeclarations.get(className); 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 // Create an instance and put evaluated fields with method declarations
final ClassInstanceValue instance = new ClassInstanceValue(className); final ClassInstanceValue instance = new ClassInstanceValue(className);
@ -30,14 +41,17 @@ public final class ObjectCreationExpression implements Expression {
} }
// Call a constructor // Call a constructor
instance.callConstructor(ctorArgs());
return instance;
}
private Value[] ctorArgs() {
final int argsSize = constructorArguments.size(); final int argsSize = constructorArguments.size();
final Value[] ctorArgs = new Value[argsSize]; final Value[] ctorArgs = new Value[argsSize];
for (int i = 0; i < argsSize; i++) { for (int i = 0; i < argsSize; i++) {
ctorArgs[i] = constructorArguments.get(i).eval(); ctorArgs[i] = constructorArguments.get(i).eval();
} }
instance.callConstructor(ctorArgs); return ctorArgs;
return instance;
} }
@Override @Override