Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(322)

Unified Diff: frog/leg/compile_time_constants.dart

Issue 9662037: Compile time constants with fields. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: rebase Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: frog/leg/compile_time_constants.dart
diff --git a/frog/leg/compile_time_constants.dart b/frog/leg/compile_time_constants.dart
index ce6da957de10eecf26b3eb80a5fb5aad5a214021..a1062ba16518ac4d4f09bcd58e28e8fb9db9b990 100644
--- a/frog/leg/compile_time_constants.dart
+++ b/frog/leg/compile_time_constants.dart
@@ -497,8 +497,8 @@ class ConstantHandler extends CompilerTask {
return constant;
}
- compileVariableWithDefinitions(VariableElement element,
- TreeElements definitions) {
+ Constant compileVariableWithDefinitions(VariableElement element,
+ TreeElements definitions) {
return measure(() {
Node node = element.parseNode(compiler);
assert(node !== null);
@@ -518,35 +518,6 @@ class ConstantHandler extends CompilerTask {
});
}
- ConstructedConstant compileObjectConstruction(Node node,
- Type type,
- List arguments) {
- if (!arguments.isEmpty()) {
- compiler.unimplemented("ConstantHandler with arguments", node: node);
- }
- ClassElement classElement = type.element;
- for (Element member in classElement.members) {
- if (Elements.isInstanceField(member)) {
- compiler.unimplemented("ConstantHandler with fields", node: node);
- }
- }
- if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) {
- compiler.unimplemented("ConstantHandler with super", node: node);
- }
- compiler.registerInstantiatedClass(classElement);
- Constant constant = new ConstructedConstant(type, arguments);
- registerCompileTimeConstant(constant);
- return constant;
- }
-
- ListConstant compileListLiteral(Node node,
- Type type,
- List<Constant> arguments) {
- Constant constant = new ListConstant(type, arguments);
- registerCompileTimeConstant(constant);
- return constant;
- }
-
/**
* Returns a [List] of static non final fields that need to be initialized.
* The list must be evaluated in order since the fields might depend on each
@@ -677,13 +648,19 @@ class ConstantHandler extends CompilerTask {
class CompileTimeConstantEvaluator extends AbstractVisitor {
final ConstantHandler constantHandler;
- final TreeElements definitions;
+ final TreeElements elements;
final Compiler compiler;
+ final Map<Element, Constant> definitions = null;
CompileTimeConstantEvaluator(this.constantHandler,
- this.definitions,
+ this.elements,
this.compiler);
+ CompileTimeConstantEvaluator.withDefinitions(this.constantHandler,
+ this.elements,
+ this.compiler,
+ this.definitions);
+
Constant evaluate(Node node) {
return node.accept(this);
}
@@ -716,7 +693,9 @@ class CompileTimeConstantEvaluator extends AbstractVisitor {
}
// TODO(floitsch): get type from somewhere.
Type type = null;
- return constantHandler.compileListLiteral(node, type, arguments);
+ Constant constant = new ListConstant(type, arguments);
+ constantHandler.registerCompileTimeConstant(constant);
+ return constant;
}
Constant visitLiteralMap(LiteralMap node) {
@@ -773,8 +752,8 @@ class CompileTimeConstantEvaluator extends AbstractVisitor {
}
// TODO(floitsch): provide better error-messages.
- visitSend(Send send) {
- Element element = definitions[send];
+ Constant visitSend(Send send) {
+ Element element = elements[send];
if (Elements.isStaticOrTopLevelField(element)) {
if (element.modifiers === null ||
!element.modifiers.isFinal()) {
@@ -802,6 +781,13 @@ class CompileTimeConstantEvaluator extends AbstractVisitor {
}
if (folded === null) error(send);
return folded;
+ } else if (Elements.isLocal(element)) {
+ if (definitions === null) error(send);
ngeoffray 2012/03/12 14:02:53 What does it mean to not have a definitions? Not b
floitsch 2012/03/12 14:37:53 Done.
+ Constant constant = definitions[element];
+ if (constant === null) {
+ compiler.internalError("Local variable without value", node: send);
+ }
+ return constant;
} else if (send.isOperator && !send.isPostfix) {
assert(send.argumentCount() == 1);
Constant left = evaluate(send.receiver);
@@ -896,27 +882,120 @@ class CompileTimeConstantEvaluator extends AbstractVisitor {
error(node);
}
- visitNewExpression(NewExpression node) {
- if (!node.isConst()) error(node);
- Send send = node.send;
- List arguments;
- if (send.arguments.isEmpty()) {
- arguments = const [];
- } else {
- arguments = [];
- for (Link<Node> link = send.arguments;
- !link.isEmpty();
- link = link.tail) {
- arguments.add(evaluate(link.head));
+ Constant visitNewExpression(NewExpression node) {
+ List<Constant> compileArguments() {
+ if (!node.isConst()) error(node);
+ Send send = node.send;
+ List<Constant> arguments;
+ if (send.arguments.isEmpty()) {
+ arguments = const [];
ngeoffray 2012/03/12 14:02:53 const <Constant>[];
floitsch 2012/03/12 14:37:53 Done.
+ } else {
+ arguments = [];
ngeoffray 2012/03/12 14:02:53 <Constant>[];
floitsch 2012/03/12 14:37:53 Done.
+ for (Link<Node> link = send.arguments;
+ !link.isEmpty();
+ link = link.tail) {
+ arguments.add(evaluate(link.head));
+ }
}
+ return arguments;
}
+
+ void assignArgumentsToParameters(
+ List<Constant> arguments,
+ FunctionParameters parameters,
+ Map<Element, Constant> constructorDefinitions) {
+ if (arguments.length != parameters.parameterCount) {
+ if (arguments.length < parameters.parameterCount &&
+ arguments.length >= parameters.requiredParameterCount) {
+ compiler.unimplemented("ConstantHandler with optional arguments",
+ node: node);
+ } else {
+ error(node);
+ }
+ }
+ int index = 0;
+ parameters.forEachParameter((Element parameter) {
+ constructorDefinitions[parameter] = arguments[index++];
+ });
+ }
+
+ void compileInitializers(Link<Node> initializers,
+ CompileTimeConstantEvaluator evaluator,
+ TreeElements constructorElements,
+ Map<Element, Constant> constructorDefinitions) {
+ for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) {
+ assert(link.head is Send);
+ if (link.head is !SendSet) {
+ // A super initializer or constructor redirection.
+ Send call = link.head;
+ assert(Initializers.isSuperConstructorCall(call) ||
+ Initializers.isConstructorRedirect(call));
+ compiler.unimplemented("ConstantHandler with this or super",
+ node: call);
+ } else {
+ // A field initializer.
+ SendSet init = link.head;
+ Link<Node> arguments = init.arguments;
+ assert(!arguments.isEmpty() && arguments.tail.isEmpty());
+ Constant fieldValue = evaluator.evaluate(arguments.head);
+ constructorDefinitions[constructorElements[init]] = fieldValue;
+ }
+ }
+ }
+
+ List<Constant> buildJsConstructorArguments(
+ ClassElement classElement,
+ Map<Element, Constant> constructorDefinitions) {
+ List<Constant> fieldValues = <Constant>[];
+ for (Element member in classElement.members) {
+ if (member.isInstanceMember() && member.kind == ElementKind.FIELD) {
+ Constant fieldValue = constructorDefinitions[member];
+ if (fieldValue === null) {
+ // Use the default value.
+ fieldValue = constantHandler.compileVariable(member);
+ }
+ fieldValues.add(fieldValue);
+ }
+ }
+ if (classElement.superclass != compiler.coreLibrary.find(Types.OBJECT)) {
+ compiler.unimplemented("ConstantHandler with super", node: node);
+ }
+ return fieldValues;
+ }
+
// TODO(floitsch): get the type from somewhere.
- Element constructorElement = definitions[node.send];
- ClassElement classElement = constructorElement.enclosingElement;
+ FunctionElement constructor = elements[node.send];
+ ClassElement classElement = constructor.enclosingElement;
+ TreeElements constructorElements =
+ compiler.resolver.resolveMethodElement(constructor);
+ FunctionExpression functionNode = constructor.parseNode(compiler);
+ NodeList initializerList = functionNode.initializers;
+ FunctionParameters parameters = constructor.computeParameters(compiler);
+
+ Map<Element, Constant> constructorDefinitions =
+ new Map<Element, Constant>();
+
+ List<Constant> arguments = compileArguments();
+ assignArgumentsToParameters(arguments, parameters, constructorDefinitions);
+ CompileTimeConstantEvaluator initializerEvaluator =
+ new CompileTimeConstantEvaluator.withDefinitions(
+ constantHandler, constructorElements, compiler,
+ constructorDefinitions);
+ if (initializerList !== null) {
+ Link<Node> initializers = functionNode.initializers.nodes;
+ compileInitializers(initializers,
+ initializerEvaluator,
+ constructorElements,
+ constructorDefinitions);
+ }
+ List<Constant> fieldValues =
+ buildJsConstructorArguments(classElement, constructorDefinitions);
+
+ compiler.registerInstantiatedClass(classElement);
Type type = new SimpleType(classElement.name, classElement);
- return constantHandler.compileObjectConstruction(node,
- type,
- arguments);
+ Constant constant = new ConstructedConstant(type, fieldValues);
+ constantHandler.registerCompileTimeConstant(constant);
+ return constant;
}
error(Node node) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698