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

Unified Diff: lib/dartdoc/frog/analyze.dart

Issue 10696191: Frog removed from dartdoc. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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 | lib/dartdoc/frog/analyze_frame.dart » ('j') | tools/create_sdk.py » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/dartdoc/frog/analyze.dart
diff --git a/lib/dartdoc/frog/analyze.dart b/lib/dartdoc/frog/analyze.dart
deleted file mode 100644
index 0ff13cca55a10abd15f61b849a1642297dc30bb3..0000000000000000000000000000000000000000
--- a/lib/dartdoc/frog/analyze.dart
+++ /dev/null
@@ -1,793 +0,0 @@
-// Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/**
- * A simple code analyzer for Dart.
- *
- * Currently used to ensure all concrete generic types are visited.
- * Also performs all static type checks - so these don't need to be
- * done in later phases.
- *
- * Ultimately, this should include abstract interpreter work. This will
- * result in an interesting split beteen this class and MethodGenerator
- * which should be turned into nothing more than a code generator.
- */
-// TODO(jimhug): This class shares too much code with MethodGenerator.
-class MethodAnalyzer implements TreeVisitor {
- MethodMember method;
- Statement body;
-
- CallFrame _frame;
-
- /**
- * Track whether or not [body] refers to any type parameters from the
- * enclosing type to advise future code generation and analysis.
- */
- bool hasTypeParams = false;
-
- MethodAnalyzer(this.method, this.body);
-
- // TODO(jimhug): Type issue with requiring CallFrame here...
- void analyze(CallFrame context) {
- var thisValue;
- // TODO(jimhug): Move Constructor analysis to here and below.
-
- if (context != null) {
- thisValue = context.thisValue;
- } else {
- thisValue = new PureStaticValue(method.declaringType, null);
- }
- var values = [];
- for (var p in method.parameters) {
- values.add(new PureStaticValue(p.type, null));
- }
- var args = new Arguments(null, values);
-
- _frame = new CallFrame(this, method, thisValue, args, context);
- _bindArguments(_frame.args);
-
- // Visit the super or this call in a constructor, if any.
- final declaredInitializers = method.definition.dynamic.initializers;
- if (declaredInitializers != null) {
- for (var init in declaredInitializers) {
- if (init is CallExpression) {
- visitCallExpression(init, true);
- }
- }
- }
-
- if (body != null) body.visit(this);
- }
-
- /* Checks whether or not a particular TypeReference Node includes references
- * to type parameters. */
- bool _hasTypeParams(node) {
- if (node is NameTypeReference) {
- var name = node.name.name;
- return (method.declaringType.lookupTypeParam(name) != null);
- } else if (node is GenericTypeReference) {
- for (var typeArg in node.typeArguments) {
- if (_hasTypeParams(typeArg)) return true;
- }
- return false;
- } else {
- // TODO(jimhug): Do we need to include FunctionTypeReference here?
- return false;
- }
- }
-
- Type resolveType(TypeReference node, bool typeErrors,
- bool allowTypeParams) {
- if (!hasTypeParams && _hasTypeParams(node)) {
- hasTypeParams = true;
- }
- return method.resolveType(node, typeErrors, allowTypeParams);
- }
-
-
- Value makeNeutral(Value inValue, SourceSpan span) {
- return new PureStaticValue(inValue.type, span);
- }
-
- void _bindArguments(Arguments args) {
- for (int i = 0; i < method.parameters.length; i++) {
- var p = method.parameters[i];
- Value currentArg = null;
- if (i < args.bareCount) {
- currentArg = args.values[i];
- } else {
- // Handle named or missing arguments
- currentArg = args.getValue(p.name);
- if (currentArg === null) {
- // TODO(jmesserly): this path won't work if we ever get here, because
- // Paramter.genValue assumes it has a MethodGenerator.
-
- // Ensure default value for param has been generated
- p.genValue(method, _frame); // TODO(jimhug): Needed here?
- if (p.value === null) {
- world.warning('missing argument at call - does not match');
- }
- currentArg = p.value;
- }
- }
-
- currentArg = makeNeutral(currentArg, p.definition.span);
-
- // TODO(jimhug): Add checks for constructor initializers.
- _frame.declareParameter(p, currentArg);
- // TODO(jimhug): Add type check?
- }
- }
-
- visitBool(Expression node) {
- return visitTypedValue(node, world.boolType);
- }
-
- visitValue(Expression node) {
- if (node == null) return null;
-
- var value = node.visit(this);
- value.checkFirstClass(node.span);
- return value;
- }
-
- /**
- * Visit [node] and ensure statically or with an runtime check that it has
- * the expected type (if specified).
- */
- visitTypedValue(Expression node, Type expectedType) {
- final val = visitValue(node);
- return val === null ? null : val.convertTo(_frame, expectedType);
- }
-
- visitVoid(Expression node) {
- // TODO(jimhug): Add some helpful diagnostics for silly void uses.
- return visitValue(node);
- }
-
-
- Arguments _visitArgs(List<ArgumentNode> arguments) {
- var args = [];
- bool seenLabel = false;
- for (var arg in arguments) {
- if (arg.label != null) {
- seenLabel = true;
- } else if (seenLabel) {
- // TODO(jimhug): Move this into parser?
- world.error('bare argument cannot follow named arguments', arg.span);
- }
- args.add(visitValue(arg.value));
- }
-
- return new Arguments(arguments, args);
- }
-
- MethodMember _makeLambdaMethod(String name, FunctionDefinition func) {
- var meth = new MethodMember.lambda(name, method.declaringType, func);
- meth.enclosingElement = method;
- meth._methodData = new MethodData(meth, _frame);
- meth.resolve();
- return meth;
- }
-
- void _pushBlock(Node node) {
- _frame.pushBlock(node);
- }
- void _popBlock(Node node) {
- _frame.popBlock(node);
- }
-
- Member _resolveBare(String name, Node node) {
- var type = _frame.method.declaringType;
- var member = type.getMember(name);
- if (member == null || member.declaringType != type) {
- var libMember = _frame.library.lookup(name, node.span);
- if (libMember !== null) return libMember;
- }
-
- if (member !== null && !member.isStatic && _frame.isStatic) {
- world.error('cannot refer to instance member from static method',
- node.span);
- }
- return member;
- }
-
- // ******************* Statements *******************
-
- void visitDietStatement(DietStatement node) {
- var parser = new Parser(node.span.file, startOffset: node.span.start);
- parser.block().visit(this);
- }
-
- void visitVariableDefinition(VariableDefinition node) {
- var isFinal = false;
- // TODO(jimhug): Clean this up and share modifier parsing somewhere.
- if (node.modifiers != null && node.modifiers[0].kind == TokenKind.FINAL) {
- isFinal = true;
- }
- var type = resolveType(node.type, false, true);
- for (int i=0; i < node.names.length; i++) {
- final name = node.names[i].name;
- var value = visitValue(node.values[i]);
- _frame.create(name, type, node.names[i], isFinal, value);
- }
- }
-
- void visitFunctionDefinition(FunctionDefinition node) {
- var meth = _makeLambdaMethod(node.name.name, node);
- // TODO(jimhug): Better FunctionValue that tracks actual function
- var funcValue = _frame.create(meth.name, meth.functionType,
- method.definition, true, null);
-
- meth.methodData.analyze();
- }
-
-
- void visitReturnStatement(ReturnStatement node) {
- if (node.value == null) {
- _frame.returns(Value.fromNull(node.span));
- } else {
- _frame.returns(visitValue(node.value));
- }
- }
-
- void visitThrowStatement(ThrowStatement node) {
- // Dart allows throwing anything, just like JS
- if (node.value != null) {
- var value = visitValue(node.value);
- } else {
- // skip
- }
- }
-
- void visitAssertStatement(AssertStatement node) {
- // be sure to walk test for static checking even is asserts disabled
- var test = visitValue(node.test); // TODO(jimhug): check bool or callable.
- }
-
- void visitBreakStatement(BreakStatement node) {
- }
-
- void visitContinueStatement(ContinueStatement node) {
- }
-
- void visitIfStatement(IfStatement node) {
- var test = visitBool(node.test);
- node.trueBranch.visit(this);
- if (node.falseBranch != null) {
- node.falseBranch.visit(this);
- }
- }
-
- void visitWhileStatement(WhileStatement node) {
- var test = visitBool(node.test);
- node.body.visit(this);
- }
-
- void visitDoStatement(DoStatement node) {
- node.body.visit(this);
- var test = visitBool(node.test);
- }
-
- void visitForStatement(ForStatement node) {
- _pushBlock(node);
- if (node.init != null) node.init.visit(this);
-
- if (node.test != null) {
- var test = visitBool(node.test);
- }
- for (var s in node.step) {
- var sv = visitVoid(s);
- }
-
- _pushBlock(node.body);
- node.body.visit(this);
- _popBlock(node.body);
-
-
- _popBlock(node);
- }
-
- void visitForInStatement(ForInStatement node) {
- // TODO(jimhug): visitValue and other cleanups here.
- var itemType = resolveType(node.item.type, false, true);
- var list = node.list.visit(this);
- _visitForInBody(node, itemType, list);
- }
-
-
- bool _isFinal(typeRef) {
- if (typeRef is GenericTypeReference) {
- typeRef = typeRef.baseType;
- } else if (typeRef is SimpleTypeReference) {
- return false;
- }
- return typeRef != null && typeRef.isFinal;
- }
-
- void _visitForInBody(ForInStatement node, Type itemType, Value list) {
- // TODO(jimhug): Check that itemType matches list members...
- _pushBlock(node);
-
- bool isFinal = _isFinal(node.item.type);
- var itemName = node.item.name.name;
- var item =
- _frame.create(itemName, itemType, node.item.name, isFinal, null);
-
- var iterator =
- list.invoke(_frame, 'iterator', node.list, Arguments.EMPTY);
-
- node.body.visit(this);
- _popBlock(node);
- }
-
- _createDI(DeclaredIdentifier di) {
- _frame.create(di.name.name, resolveType(di.type, false, true), di.name,
- true, null);
- }
-
- void visitTryStatement(TryStatement node) {
- _pushBlock(node.body);
- node.body.visit(this);
- _popBlock(node.body);
- if (node.catches.length > 0) {
- for (int i = 0; i < node.catches.length; i++) {
- var catch_ = node.catches[i];
- _pushBlock(catch_);
- _createDI(catch_.exception);
- if (catch_.trace !== null) {
- _createDI(catch_.trace);
- }
- catch_.body.visit(this);
- _popBlock(catch_);
- }
- }
-
- if (node.finallyBlock != null) {
- node.finallyBlock.visit(this);
- }
- }
-
- void visitSwitchStatement(SwitchStatement node) {
- var test = visitValue(node.test);
- for (var case_ in node.cases) {
- _pushBlock(case_);
-
- for (int i=0; i < case_.cases.length; i++) {
- var expr = case_.cases[i];
- if (expr == null) {
- //skip
- } else {
- var value = visitValue(expr);
- }
- }
- _visitAllStatements(case_.statements);
- _popBlock(case_);
- }
- }
-
- _visitAllStatements(statementList) {
- for (int i = 0; i < statementList.length; i++) {
- var stmt = statementList[i];
- stmt.visit(this);
- }
- }
-
- void visitBlockStatement(BlockStatement node) {
- _pushBlock(node);
- _visitAllStatements(node.body);
- _popBlock(node);
- }
-
- void visitLabeledStatement(LabeledStatement node) {
- node.body.visit(this);
- }
-
- void visitExpressionStatement(ExpressionStatement node) {
- var value = visitVoid(node.body);
- }
-
- void visitEmptyStatement(EmptyStatement node) {
- }
-
-
-
- // ******************* Expressions *******************
- visitLambdaExpression(LambdaExpression node) {
- var name = (node.func.name != null) ? node.func.name.name : '';
-
- MethodMember meth = _makeLambdaMethod(name, node.func);
- // TODO(jimhug): Worry about proper scope for recursive lambda.
- meth.methodData.analyze();
-
- return _frame._makeValue(world.functionType, node);
- }
-
- analyzeInitializerConstructorCall(CallExpression node,
- Expression receiver,
- String name) {
- var type = _frame.method.declaringType;
- if (receiver is SuperExpression) {
- type = type.parent;
- }
- var member = type.getConstructor(name == null ? '' : name);
- if (member !== null) {
- return member.invoke(_frame, node, _frame.makeThisValue(node),
- _visitArgs(node.arguments));
- } else {
- String constructorName = name == null ? '' : '.$name';
- world.warning('cannot find constructor "${type.name}$constructorName"',
- node.span);
- return _frame._makeValue(world.varType, node);
- }
- }
-
- bool isThisOrSuper(Expression node) {
- return node is ThisExpression || node is SuperExpression;
- }
-
- Value visitCallExpression(CallExpression node,
- [bool visitingInitializers = false]) {
- var target;
- var position = node.target;
- var name = ':call';
- if (node.target is DotExpression) {
- DotExpression dot = node.target;
- target = dot.self.visit(this);
- name = dot.name.name;
- if (isThisOrSuper(dot.self) && visitingInitializers) {
- return analyzeInitializerConstructorCall(node, dot.self, name);
- } else {
- position = dot.name;
- }
- } else if (isThisOrSuper(node.target) && visitingInitializers) {
- return analyzeInitializerConstructorCall(node, node.target, null);
- } else if (node.target is VarExpression) {
- VarExpression varExpr = node.target;
- name = varExpr.name.name;
- // First check in block scopes.
- target = _frame.lookup(name);
- if (target != null) {
- return target.get(position).invoke(_frame, ':call', node,
- _visitArgs(node.arguments));
- }
-
- var member = _resolveBare(name, varExpr.name);
- if (member !== null) {
- return member.invoke(_frame, node, _frame.makeThisValue(node),
- _visitArgs(node.arguments));
- } else {
- world.warning('cannot find "$name"', node.span);
- return _frame._makeValue(world.varType, node);
- }
- } else {
- target = node.target.visit(this);
- }
-
- return target.invoke(_frame, name, position, _visitArgs(node.arguments));
- }
-
- Value visitIndexExpression(IndexExpression node) {
- var target = visitValue(node.target);
- var index = visitValue(node.index);
-
- return target.invoke(_frame, ':index', node,
- new Arguments(null, [index]));
- }
-
-
- Value visitBinaryExpression(BinaryExpression node, [bool isVoid = false]) {
- final kind = node.op.kind;
-
- if (kind == TokenKind.AND || kind == TokenKind.OR) {
- var xb = visitBool(node.x);
- var yb = visitBool(node.y);
- return xb.binop(kind, yb, _frame, node);
- }
-
- final assignKind = TokenKind.kindFromAssign(node.op.kind);
- if (assignKind == -1) {
- final x = visitValue(node.x);
- final y = visitValue(node.y);
- return x.binop(kind, y, _frame, node);
- } else {
- return _visitAssign(assignKind, node.x, node.y, node);
- }
- }
-
- /**
- * Visits an assignment expression.
- */
- Value _visitAssign(int kind, Expression xn, Expression yn, Node position) {
- if (xn is VarExpression) {
- return _visitVarAssign(kind, xn, yn, position);
- } else if (xn is IndexExpression) {
- return _visitIndexAssign(kind, xn, yn, position);
- } else if (xn is DotExpression) {
- return _visitDotAssign(kind, xn, yn, position);
- } else {
- world.error('illegal lhs', xn.span);
- }
- }
-
- _visitVarAssign(int kind, VarExpression xn, Expression yn, Node node) {
- final value = visitValue(yn);
- final name = xn.name.name;
-
- // First check in block scopes.
- var slot = _frame.lookup(name);
- if (slot != null) {
- slot.set(value);
- } else {
- var member = _resolveBare(name, xn.name);
- if (member !== null) {
- member._set(_frame, node, _frame.makeThisValue(node), value);
- } else {
- world.warning('cannot find "$name"', node.span);
- }
- }
- return _frame._makeValue(value.type, node);
- }
-
- _visitIndexAssign(int kind, IndexExpression xn, Expression yn,
- Node position) {
- var target = visitValue(xn.target);
- var index = visitValue(xn.index);
- var y = visitValue(yn);
-
- return target.setIndex(_frame, index, position, y, kind: kind);
- }
-
- _visitDotAssign(int kind, DotExpression xn, Expression yn, Node position) {
- // This is not visitValue because types members are assignable.
- var target = xn.self.visit(this);
- var y = visitValue(yn);
-
- return target.set_(_frame, xn.name.name, xn.name, y, kind: kind);
- }
-
- visitUnaryExpression(UnaryExpression node) {
- var value = visitValue(node.self);
- switch (node.op.kind) {
- case TokenKind.INCR:
- case TokenKind.DECR:
- return value.binop(TokenKind.ADD,
- _frame._makeValue(world.intType, node), _frame, node);
- }
- return value.unop(node.op.kind, _frame, node);
- }
-
- visitDeclaredIdentifier(DeclaredIdentifier node) {
- world.error('Expected expression', node.span);
- }
-
- visitAwaitExpression(AwaitExpression node) {
- world.internalError(
- 'Await expressions should have been eliminated before code generation',
- node.span);
- }
-
- Value visitPostfixExpression(PostfixExpression node,
- [bool isVoid = false]) {
- var value = visitValue(node.body);
-
- return _frame._makeValue(value.type, node);
- }
-
- Value visitNewExpression(NewExpression node) {
- var typeRef = node.type;
-
- var constructorName = '';
- if (node.name != null) {
- constructorName = node.name.name;
- }
-
- // Named constructors and library prefixes, oh my!
- // At last, we can collapse the ambiguous wave function...
- if (constructorName == '' && typeRef is NameTypeReference &&
- typeRef.names != null) {
-
- // Pull off the last name from the type, guess it's the constructor name.
- var names = new List.from(typeRef.names);
- constructorName = names.removeLast().name;
- if (names.length == 0) names = null;
-
- typeRef = new NameTypeReference(
- typeRef.isFinal, typeRef.name, names, typeRef.span);
- }
-
- var type = resolveType(typeRef, true, true);
- if (type.isTop) {
- type = type.library.findTypeByName(constructorName);
- if (type == null) {
- world.error('cannot resolve type $constructorName', node.span);
- }
- constructorName = '';
- }
-
- if (type is ParameterType) {
- world.error('cannot instantiate a type parameter', node.span);
- return _frame._makeValue(world.varType, node);
- }
-
- var m = type.getConstructor(constructorName);
- if (m == null) {
- var name = type.jsname;
- if (type.isVar) {
- name = typeRef.name.name;
- }
- world.warning('no matching constructor for $name', node.span);
- return _frame._makeValue(type, node);
- }
-
- if (node.isConst) {
- if (!m.isConst) {
- world.error('can\'t use const on a non-const constructor', node.span);
- }
- for (var arg in node.arguments) {
- // TODO(jimhug): Remove this double walk of arguments.
- if (!visitValue(arg.value).isConst) {
- world.error('const constructor expects const arguments', arg.span);
- }
- }
- }
-
-
- var args = _visitArgs(node.arguments);
- var target = new TypeValue(type, typeRef.span);
- return new PureStaticValue(type, node.span, node.isConst);
- }
-
- Value visitListExpression(ListExpression node) {
- var argValues = [];
- var listType = world.listType;
- var type = world.varType;
- if (node.itemType != null) {
- type = resolveType(node.itemType, true, !node.isConst);
- if (node.isConst && (type is ParameterType || type.hasTypeParams)) {
- world.error('type parameter cannot be used in const list literals');
- }
- listType = listType.getOrMakeConcreteType([type]);
- }
- for (var item in node.values) {
- var arg = visitTypedValue(item, type);
- argValues.add(arg);
- // TODO(jimhug): Reenable these checks here - and remove from MethodGen
- //if (node.isConst && !arg.isConst) {
- // world.error('const list can only contain const values', arg.span);
- //}
- }
-
- world.listFactoryType.markUsed();
-
- return new PureStaticValue(listType, node.span, node.isConst);
- }
-
-
- Value visitMapExpression(MapExpression node) {
- var values = <Value>[];
- var valueType = world.varType, keyType = world.stringType;
- var mapType = world.mapType; // TODO(jimhug): immutable type?
- if (node.valueType !== null) {
- if (node.keyType !== null) {
- keyType = method.resolveType(node.keyType, true, !node.isConst);
- // TODO(jimhug): Would be nice to allow arbitrary keys here (this is
- // currently not allowed by the spec).
- if (!keyType.isString) {
- world.error('the key type of a map literal must be "String"',
- keyType.span);
- }
- if (node.isConst &&
- (keyType is ParameterType || keyType.hasTypeParams)) {
- world.error('type parameter cannot be used in const map literals');
- }
- }
-
- valueType = resolveType(node.valueType, true, !node.isConst);
- if (node.isConst &&
- (valueType is ParameterType || valueType.hasTypeParams)) {
- world.error('type parameter cannot be used in const map literals');
- }
-
- mapType = mapType.getOrMakeConcreteType([keyType, valueType]);
- }
-
- for (int i = 0; i < node.items.length; i += 2) {
- var key = visitTypedValue(node.items[i], keyType);
- // TODO(jimhug): Reenable these checks here - and remove from MethodGen
- //if (node.isConst && !key.isConst) {
- // world.error('const map can only contain const keys', key.span);
- //}
- values.add(key);
-
- var value = visitTypedValue(node.items[i + 1], valueType);
- if (node.isConst && !value.isConst) {
- world.error('const map can only contain const values', value.span);
- }
- values.add(value);
- }
-
- return new PureStaticValue(mapType, node.span, node.isConst);
- }
-
-
- Value visitConditionalExpression(ConditionalExpression node) {
- var test = visitBool(node.test);
- var trueBranch = visitValue(node.trueBranch);
- var falseBranch = visitValue(node.falseBranch);
-
- // TODO(jimhug): Should be unioning values, not just types.
- return _frame._makeValue(Type.union(trueBranch.type, falseBranch.type),
- node);
- }
-
- Value visitIsExpression(IsExpression node) {
- var value = visitValue(node.x);
- var type = resolveType(node.type, false, true);
- return _frame._makeValue(world.boolType, node);
- }
-
- Value visitParenExpression(ParenExpression node) {
- return visitValue(node.body);
- }
-
- Value visitDotExpression(DotExpression node) {
- // Types are legal targets of .
- var target = node.self.visit(this);
- return target.get_(_frame, node.name.name, node);
- }
-
-
- Value visitVarExpression(VarExpression node) {
- final name = node.name.name;
-
- // First check in block scopes.
- var slot = _frame.lookup(name);
- if (slot != null) {
- return slot.get(node);
- }
-
- var member = _resolveBare(name, node.name);
- if (member !== null) {
- if (member is TypeMember) {
- return new PureStaticValue(member.dynamic.type, node.span, true,
- true);
- } else {
- return member._get(_frame, node, _frame.makeThisValue(node));
- }
- } else {
- world.warning('cannot find "$name"', node.span);
- return _frame._makeValue(world.varType, node);
- }
- }
-
- Value visitThisExpression(ThisExpression node) {
- return _frame.makeThisValue(node);
- }
-
- Value visitSuperExpression(SuperExpression node) {
- return _frame.makeSuperValue(node);
- }
-
- Value visitLiteralExpression(LiteralExpression node) {
- return new PureStaticValue(node.value.type, node.span, true);
- }
-
- Value visitStringConcatExpression(StringConcatExpression node) {
- bool isConst = true;
- node.strings.forEach((each) {
- if (!visitValue(each).isConst) isConst = false;
- });
- return new PureStaticValue(world.stringType, node.span, isConst);
- }
-
- Value visitStringInterpExpression(StringInterpExpression node) {
- bool isConst = true;
- node.pieces.forEach((each) {
- if (!visitValue(each).isConst) isConst = false;
- });
- return new PureStaticValue(world.stringType, node.span, isConst);
- }
-}
-
« no previous file with comments | « no previous file | lib/dartdoc/frog/analyze_frame.dart » ('j') | tools/create_sdk.py » ('J')

Powered by Google App Engine
This is Rietveld 408576698