| Index: frog/value.dart
|
| diff --git a/frog/value.dart b/frog/value.dart
|
| index a1c7499c7cfb75b8e4bc86138662e5c8aa8e7236..b13ea6fa35da5112158c5cb7b6ada53445b41940 100644
|
| --- a/frog/value.dart
|
| +++ b/frog/value.dart
|
| @@ -3,6 +3,138 @@
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
|
|
| +interface CallingContext {
|
| + MemberSet findMembers(String name);
|
| + CounterLog get counters();
|
| + Library get library();
|
| + bool get isStatic();
|
| + MethodMember get method();
|
| +
|
| + bool get needsCode();
|
| + bool get showWarnings();
|
| +
|
| + // Hopefully remove the 5 members below that are only used for code gen.
|
| + String _makeThisCode();
|
| +
|
| + Value getTemp(Value value);
|
| + VariableValue forceTemp(Value value);
|
| + Value assignTemp(Value tmp, Value v);
|
| + void freeTemp(VariableValue value);
|
| +}
|
| +
|
| +// TODO(jimhug): Value needs better separation into three parts:
|
| +// 1. Static analysis
|
| +// 2. Type inferred abstract interpretation analysis
|
| +// 3. Actual code generation
|
| +/**
|
| + * This subtype of value is the one and only version used for static
|
| + * analysis. It has no code and its type is always the static type.
|
| + */
|
| +class PureStaticValue extends Value {
|
| + bool isConst;
|
| + bool isType;
|
| +
|
| + // TODO(jimhug): Can we remove span?
|
| + PureStaticValue(Type type, SourceSpan span,
|
| + [this.isConst = false, this.isType = false]):
|
| + super(type, null, span);
|
| +
|
| + Member getMem(CallingContext context, String name, Node node) {
|
| + var member = type.getMember(name);
|
| +
|
| + if (member == null) {
|
| + world.warning('can not find "$name" on "${type.name}"', node.span);
|
| + }
|
| +
|
| + if (isType && !member.isStatic) {
|
| + world.error('can not refer to instance member as static', node.span);
|
| + }
|
| +
|
| + return member;
|
| + }
|
| +
|
| + Value get_(CallingContext context, String name, Node node) {
|
| + if (type.isVar) return new PureStaticValue(world.varType, node.span);
|
| + var member = getMem(context, name, node);
|
| + if (member == null) return new PureStaticValue(world.varType, node.span);
|
| +
|
| + return member._get(context, node, this);
|
| + }
|
| +
|
| + Value set_(CallingContext context, String name, Node node, Value value,
|
| + [int kind=0, int returnKind=ReturnKind.IGNORE]) {
|
| + if (type.isVar) return new PureStaticValue(world.varType, node.span);
|
| +
|
| + var member = getMem(context, name, node);
|
| + if (member != null) {
|
| + member._set(context, node, this, value);
|
| + }
|
| + return new PureStaticValue(value.type, node.span);
|
| + }
|
| +
|
| + Value setIndex(CallingContext context, Value index, Node node, Value value,
|
| + [int kind=0, int returnKind=ReturnKind.IGNORE]) {
|
| + return invoke(context, ':setindex', node,
|
| + new Arguments(null, [index, value]));
|
| + }
|
| +
|
| + Value unop(int kind, CallingContext context, var node) {
|
| + switch (kind) {
|
| + case TokenKind.NOT:
|
| + // TODO(jimhug): Issue #359 seeks to clarify this behavior.
|
| + // ?var newVal = convertTo(context, world.nonNullBool);
|
| + return new PureStaticValue(world.boolType, node.span);
|
| + case TokenKind.ADD:
|
| + if (!isConst && !type.isNum) {
|
| + world.error('no unary add operator in dart', node.span);
|
| + }
|
| + return new PureStaticValue(world.numType, node.span);
|
| + case TokenKind.SUB:
|
| + return invoke(context, ':negate', node, Arguments.EMPTY);
|
| + case TokenKind.BIT_NOT:
|
| + return invoke(context, ':bit_not', node, Arguments.EMPTY);
|
| + }
|
| + world.internalError('unimplemented: ${node.op}', node.span);
|
| + }
|
| +
|
| + Value binop(int kind, Value other, CallingContext context, var node) {
|
| + var isConst = isConst && other.isConst;
|
| +
|
| +
|
| + switch (kind) {
|
| + case TokenKind.AND:
|
| + case TokenKind.OR:
|
| + return new PureStaticValue(world.boolType, node.span, isConst);
|
| + case TokenKind.EQ_STRICT:
|
| + return new PureStaticValue(world.boolType, node.span, isConst);
|
| + case TokenKind.NE_STRICT:
|
| + return new PureStaticValue(world.boolType, node.span, isConst);
|
| + }
|
| +
|
| + var name = kind == TokenKind.NE ? ':ne': TokenKind.binaryMethodName(kind);
|
| + var ret = invoke(context, name, node, new Arguments(null, [other]));
|
| + if (isConst) {
|
| + ret = new PureStaticValue(ret.type, node.span, isConst);
|
| + }
|
| + return ret;
|
| + }
|
| +
|
| +
|
| + Value invoke(CallingContext context, String name, Node node,
|
| + Arguments args) {
|
| + if (type.isVar) return new PureStaticValue(world.varType, node.span);
|
| + if (type.isFunction && name == ':call') {
|
| + return new PureStaticValue(world.varType, node.span);
|
| + }
|
| +
|
| + var member = getMem(context, name, node);
|
| + if (member == null) return new PureStaticValue(world.varType, node.span);
|
| +
|
| + return member.invoke(context, node, this, args);
|
| + }
|
| +}
|
| +
|
| +
|
| /**
|
| * Represents a meta-value for code generation.
|
| */
|
| @@ -83,7 +215,7 @@ class Value {
|
|
|
| // TODO(jimhug): Fix these names once get/set are truly pseudo-keywords.
|
| // See issue #379.
|
| - Value get_(MethodGenerator context, String name, Node node) {
|
| + Value get_(CallingContext context, String name, Node node) {
|
| final member = _resolveMember(context, name, node);
|
| if (member != null) {
|
| return member._get(context, node, this);
|
| @@ -92,9 +224,9 @@ class Value {
|
| }
|
| }
|
|
|
| - Value set_(MethodGenerator context, String name, Node node, Value value,
|
| - [bool isDynamic=false, int kind=0, int returnKind=ReturnKind.IGNORE]) {
|
| - final member = _resolveMember(context, name, node, isDynamic);
|
| + Value set_(CallingContext context, String name, Node node, Value value,
|
| + [int kind=0, int returnKind=ReturnKind.IGNORE]) {
|
| + final member = _resolveMember(context, name, node);
|
| if (member != null) {
|
| var thisValue = this;
|
| var thisTmp = null;
|
| @@ -117,7 +249,7 @@ class Value {
|
| value = context.assignTemp(retTmp, value);
|
| }
|
|
|
| - var ret = member._set(context, node, thisValue, value, isDynamic);
|
| + var ret = member._set(context, node, thisValue, value);
|
| if (thisTmp != null && thisTmp != this) context.freeTemp(thisTmp);
|
| if (retTmp != null) {
|
| context.freeTemp(retTmp);
|
| @@ -133,9 +265,9 @@ class Value {
|
| }
|
|
|
| // TODO(jimhug): This method body has too much in common with set_ above.
|
| - Value setIndex(MethodGenerator context, Value index, Node node, Value value,
|
| - [bool isDynamic=false, int kind=0, int returnKind=ReturnKind.IGNORE]) {
|
| - final member = _resolveMember(context, ':setindex', node, isDynamic);
|
| + Value setIndex(CallingContext context, Value index, Node node, Value value,
|
| + [int kind=0, int returnKind=ReturnKind.IGNORE]) {
|
| + final member = _resolveMember(context, ':setindex', node);
|
| if (member != null) {
|
| var thisValue = this;
|
| var indexValue = index;
|
| @@ -169,7 +301,7 @@ class Value {
|
| }
|
|
|
| var ret = member.invoke(context, node, thisValue,
|
| - new Arguments(null, [indexValue, value]), isDynamic);
|
| + new Arguments(null, [indexValue, value]));
|
| if (thisTmp != null && thisTmp != this) context.freeTemp(thisTmp);
|
| if (indexTmp != null && indexTmp != index) context.freeTemp(indexTmp);
|
| if (retTmp != null) {
|
| @@ -185,10 +317,10 @@ class Value {
|
| }
|
| }
|
|
|
| - //Value getIndex(MethodGenerator context, Value index, var node) {
|
| + //Value getIndex(CallingContext context, Value index, var node) {
|
| //}
|
|
|
| - Value unop(int kind, MethodGenerator context, var node) {
|
| + Value unop(int kind, CallingContext context, var node) {
|
| switch (kind) {
|
| case TokenKind.NOT:
|
| // TODO(jimhug): Issue #359 seeks to clarify this behavior.
|
| @@ -205,19 +337,49 @@ class Value {
|
| world.internalError('unimplemented: ${node.op}', node.span);
|
| }
|
|
|
| - Value binop(int kind, Value other, MethodGenerator context, var node) {
|
| + bool _mayOverrideEqual() {
|
| + // TODO(jimhug): Need to check subtypes as well
|
| + return type.isVar || type.isObject ||
|
| + !type.getMember(':eq').declaringType.isObject;
|
| + }
|
| +
|
| + Value binop(int kind, Value other, CallingContext context, var node) {
|
| switch (kind) {
|
| case TokenKind.AND:
|
| case TokenKind.OR:
|
| final code = '${code} ${node.op} ${other.code}';
|
| return new Value(world.nonNullBool, code, node.span);
|
| - // TODO(jimhug): Lot's to resolve here.
|
| + // TODO(jimhug): Wrong on primitives, need new fix for null == undefined
|
| case TokenKind.EQ_STRICT:
|
| return new Value(world.nonNullBool, '${code} == ${other.code}',
|
| node.span);
|
| case TokenKind.NE_STRICT:
|
| return new Value(world.nonNullBool, '${code} != ${other.code}',
|
| node.span);
|
| +
|
| + case TokenKind.EQ:
|
| + if (other.code == 'null') {
|
| + if (!_mayOverrideEqual()) {
|
| + return new Value(world.nonNullBool, '${code} == ${other.code}',
|
| + node.span);
|
| + }
|
| + } else if (code == 'null') {
|
| + return new Value(world.nonNullBool, '${code} == ${other.code}',
|
| + node.span);
|
| + }
|
| + break;
|
| + case TokenKind.NE:
|
| + if (other.code == 'null') {
|
| + if (!_mayOverrideEqual()) {
|
| + return new Value(world.nonNullBool, '${code} != ${other.code}',
|
| + node.span);
|
| + }
|
| + } else if (code == 'null') {
|
| + return new Value(world.nonNullBool, '${code} != ${other.code}',
|
| + node.span);
|
| + }
|
| + break;
|
| +
|
| }
|
|
|
| var name = kind == TokenKind.NE ? ':ne': TokenKind.binaryMethodName(kind);
|
| @@ -225,9 +387,8 @@ class Value {
|
| }
|
|
|
|
|
| - Value invoke(MethodGenerator context, String name, Node node, Arguments args,
|
| - [bool isDynamic=false]) {
|
| -
|
| + Value invoke(CallingContext context, String name, Node node,
|
| + Arguments args) {
|
| // TODO(jmesserly): it'd be nice to remove these special cases
|
| // We could create a :call in world members, and have that handle the
|
| // canInvoke/Invoke logic.
|
| @@ -246,21 +407,12 @@ class Value {
|
| }
|
| }
|
|
|
| - var member = _resolveMember(context, name, node, isDynamic);
|
| + var member = _resolveMember(context, name, node);
|
| if (member == null) {
|
| return invokeNoSuchMethod(context, name, node, args);
|
| } else {
|
| - return member.invoke(context, node, this, args, isDynamic);
|
| - }
|
| - }
|
| -
|
| - bool canInvoke(MethodGenerator context, String name, Arguments args) {
|
| - if (type.isVarOrFunction && name == ':call') {
|
| - return true;
|
| + return member.invoke(context, node, this, args);
|
| }
|
| -
|
| - var member = _resolveMember(context, name, null, isDynamic:true);
|
| - return member != null && member.canInvoke(context, args);
|
| }
|
|
|
| /**
|
| @@ -276,13 +428,13 @@ class Value {
|
| // TODO(jimhug): Handle more precise types here, i.e. consts or closed...
|
| bool get isPreciseType() => isSuper || isType;
|
|
|
| - void _missingMemberError(MethodGenerator context, String name, bool isDynamic, Node node) {
|
| + void _missingMemberError(CallingContext context, String name, Node node) {
|
| bool onStaticType = false;
|
| if (type != staticType) {
|
| onStaticType = staticType.getMember(name) !== null;
|
| }
|
|
|
| - if (!onStaticType && !isDynamic &&
|
| + if (!onStaticType && context.showWarnings &&
|
| !_isVarOrParameterType(staticType) && !_hasOverriddenNoSuchMethod()) {
|
| // warn if the member was not found, or error if it is a static lookup.
|
| var typeName = staticType.name;
|
| @@ -298,16 +450,14 @@ class Value {
|
|
|
|
|
|
|
| - MemberSet _tryResolveMember(MethodGenerator context, String name, bool isDynamic, Node node) {
|
| + MemberSet _tryResolveMember(CallingContext context, String name, Node node) {
|
| var member = type.getMember(name);
|
| if (member == null) {
|
| - _missingMemberError(context, name, isDynamic, node);
|
| + _missingMemberError(context, name, node);
|
| return null;
|
| } else {
|
| - if (isType && !member.isStatic) {
|
| - if (!isDynamic) {
|
| - world.error('can not refer to instance member as static', node.span);
|
| - }
|
| + if (isType && !member.isStatic && context.showWarnings) {
|
| + world.error('can not refer to instance member as static', node.span);
|
| return null;
|
| }
|
| }
|
| @@ -328,17 +478,16 @@ class Value {
|
| }
|
|
|
| // TODO(jimhug): Better type here - currently is union(Member, MemberSet)
|
| - MemberSet _resolveMember(MethodGenerator context, String name, Node node,
|
| - [bool isDynamic=false]) {
|
| + MemberSet _resolveMember(CallingContext context, String name, Node node) {
|
| var member = null;
|
| if (!_shouldBindDynamically()) {
|
| - member = _tryResolveMember(context, name, isDynamic, node);
|
| + member = _tryResolveMember(context, name, node);
|
| }
|
|
|
| // Fall back to a dynamic operation for instance members
|
| if (member == null && !isSuper && !isType) {
|
| member = context.findMembers(name);
|
| - if (member == null && !isDynamic) {
|
| + if (member == null && context.showWarnings) {
|
| var where = 'the world';
|
| if (name.startsWith('_')) {
|
| where = 'library "${context.library.name}"';
|
| @@ -358,7 +507,7 @@ class Value {
|
| }
|
|
|
| /** Generate a call to an unknown function type. */
|
| - Value _varCall(MethodGenerator context, Node node, Arguments args) {
|
| + Value _varCall(CallingContext context, Node node, Arguments args) {
|
| // TODO(jmesserly): calls to unknown functions will bypass type checks,
|
| // which normally happen on the caller side, or in the generated stub for
|
| // dynamic method calls. What should we do?
|
| @@ -368,7 +517,7 @@ class Value {
|
|
|
| /** True if convertTo would generate a conversion. */
|
| bool needsConversion(Type toType) {
|
| - var c = convertTo(null, toType, isDynamic:true);
|
| + var c = convertTo(null, toType);
|
| return c == null || code != c.code;
|
| }
|
|
|
| @@ -378,11 +527,10 @@ class Value {
|
| * checks when --enable_type_checks is enabled, and wrapping callback
|
| * functions passed to the dom so we can restore their isolate context.
|
| */
|
| - Value convertTo(MethodGenerator context, Type toType,
|
| - [bool isDynamic=false]) {
|
| + Value convertTo(CallingContext context, Type toType) {
|
|
|
| // Issue type warnings unless we are processing a dynamic operation.
|
| - bool checked = !isDynamic;
|
| + bool checked = context != null && context.showWarnings;
|
|
|
| var callMethod = toType.getCallMethod();
|
| if (callMethod != null) {
|
| @@ -420,19 +568,17 @@ class Value {
|
|
|
| // Generate a runtime checks if they're turned on, otherwise skip it.
|
| if (options.enableTypeChecks) {
|
| - if (context == null && isDynamic) {
|
| + if (context == null) {
|
| // If we're called from needsConversion, we don't need a context.
|
| // Just return null so it knows a conversion is required.
|
| return null;
|
| }
|
| - return _typeAssert(context, toType, isDynamic);
|
| + return _typeAssert(context, toType);
|
| } else {
|
| return changeStaticType(toType);
|
| }
|
| }
|
|
|
| - // TODO(jmesserly): I think we can replace our usage of the "isDynamic" flag
|
| - // by changing the static type of the target to "Dynamic" instead.
|
| changeStaticType(Type toType) {
|
| // Ensure that we return something with the right type for inference
|
| // purposes.
|
| @@ -484,7 +630,7 @@ class Value {
|
| * [instanceOf], but it allows null since Dart types are nullable.
|
| * Also it will throw a TypeError if it gets the wrong type.
|
| */
|
| - Value _typeAssert(MethodGenerator context, Type toType, bool isDynamic) {
|
| + Value _typeAssert(CallingContext context, Type toType) {
|
| if (toType is ParameterType) {
|
| ParameterType p = toType;
|
| toType = p.extendsType;
|
| @@ -506,8 +652,7 @@ class Value {
|
| new TypeValue(world.typeErrorType, null),
|
| new Arguments(null, [
|
| new Value(world.objectType, paramName, null),
|
| - new Value(world.stringType, '"${toType.name}"', null)]),
|
| - isDynamic);
|
| + new Value(world.stringType, '"${toType.name}"', null)]));
|
| world.gen.corejs.useThrow = true;
|
| return '\$throw(${result.code})';
|
| });
|
| @@ -575,7 +720,7 @@ function \$assert_${toType.name}(x) {
|
| * - Otherwise add a fake member to test for. This value is generated
|
| * as a function so that it can be called for a runtime failure.
|
| */
|
| - Value instanceOf(MethodGenerator context, Type toType, SourceSpan span,
|
| + Value instanceOf(CallingContext context, Type toType, SourceSpan span,
|
| [bool isTrue=true, bool forceCheck=false]) {
|
| // TODO(jimhug): Optimize away tests that will always pass unless
|
| // forceCheck is true.
|
| @@ -601,8 +746,9 @@ function \$assert_${toType.name}(x) {
|
| testCode = "(typeof($code) ${isTrue ? '==' : '!='} '$typeofName')";
|
| }
|
| }
|
| - if (toType.isClass && toType is !ConcreteType
|
| - && !toType.isHiddenNativeType) {
|
| +
|
| + if (toType.isClass
|
| + && !toType.isHiddenNativeType && !toType.isConcreteGeneric) {
|
| toType.markUsed();
|
| testCode = '($code instanceof ${toType.jsname})';
|
| if (!isTrue) {
|
| @@ -644,7 +790,7 @@ function \$assert_${toType.name}(x) {
|
| span);
|
| }
|
|
|
| - Value invokeNoSuchMethod(MethodGenerator context, String name, Node node,
|
| + Value invokeNoSuchMethod(CallingContext context, String name, Node node,
|
| [Arguments args]) {
|
| if (isType) {
|
| world.error('member lookup failed for "$name"', node.span);
|
| @@ -735,7 +881,7 @@ class NullValue extends EvaluatedValue {
|
|
|
| String get code() => 'null';
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| if (other is! NullValue) return super.binop(kind, other, context, node);
|
|
|
| final c = isConst && other.isConst;
|
| @@ -761,7 +907,7 @@ class BoolValue extends EvaluatedValue {
|
|
|
| String get code() => actualValue ? 'true' : 'false';
|
|
|
| - Value unop(int kind, MethodGenerator context, var node) {
|
| + Value unop(int kind, CallingContext context, var node) {
|
| switch (kind) {
|
| case TokenKind.NOT:
|
| return new BoolValue(!actualValue, isConst, node.span);
|
| @@ -769,7 +915,7 @@ class BoolValue extends EvaluatedValue {
|
| return super.unop(kind, context, node);
|
| }
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| if (other is! BoolValue) return super.binop(kind, other, context, node);
|
|
|
| final c = isConst && other.isConst;
|
| @@ -801,7 +947,7 @@ class IntValue extends EvaluatedValue {
|
| // TODO(jimhug): Only add parens when needed.
|
| String get code() => '(${actualValue})';
|
|
|
| - Value unop(int kind, MethodGenerator context, var node) {
|
| + Value unop(int kind, CallingContext context, var node) {
|
| switch (kind) {
|
| case TokenKind.ADD:
|
| // This is allowed on numeric constants only
|
| @@ -815,7 +961,7 @@ class IntValue extends EvaluatedValue {
|
| }
|
|
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| final c = isConst && other.isConst;
|
| final s = node.span;
|
| if (other is IntValue) {
|
| @@ -907,7 +1053,7 @@ class DoubleValue extends EvaluatedValue {
|
|
|
| String get code() => '(${actualValue})';
|
|
|
| - Value unop(int kind, MethodGenerator context, var node) {
|
| + Value unop(int kind, CallingContext context, var node) {
|
| switch (kind) {
|
| case TokenKind.ADD:
|
| // This is allowed on numeric constants only
|
| @@ -918,7 +1064,7 @@ class DoubleValue extends EvaluatedValue {
|
| return super.unop(kind, context, node);
|
| }
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| final c = isConst && other.isConst;
|
| final s = node.span;
|
| if (other is DoubleValue) {
|
| @@ -999,7 +1145,7 @@ class StringValue extends EvaluatedValue {
|
| StringValue(this.actualValue, bool isConst, SourceSpan span):
|
| super(isConst, world.stringType, span);
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| if (other is! StringValue) return super.binop(kind, other, context, node);
|
|
|
| final c = isConst && other.isConst;
|
| @@ -1078,12 +1224,12 @@ class ListValue extends EvaluatedValue {
|
|
|
| var v = new Value(world.listType, listCode, span);
|
| final immutableListCtor = world.immutableListType.getConstructor('from');
|
| - final result = immutableListCtor.invoke(null, null,
|
| + final result = immutableListCtor.invoke(world.gen.mainContext, null,
|
| new TypeValue(v.type, span), new Arguments(null, [v]));
|
| return result.code;
|
| }
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| // TODO(jimhug): Support int/double better
|
| if (other is! ListValue) return super.binop(kind, other, context, node);
|
|
|
| @@ -1119,7 +1265,7 @@ class MapValue extends EvaluatedValue {
|
| var tp = world.coreimpl.topType;
|
| Member f = isConst ? tp.getMember('_constMap') : tp.getMember('_map');
|
| // TODO(jimhug): Clean up invoke signature
|
| - var value = f.invoke(null, null, new TypeValue(tp, null),
|
| + var value = f.invoke(world.gen.mainContext, null, new TypeValue(tp, null),
|
| new Arguments(null, [items]));
|
| return value.code;
|
| }
|
| @@ -1130,7 +1276,7 @@ class MapValue extends EvaluatedValue {
|
| return world.gen.globalForConst(this, values);
|
| }
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| if (other is! MapValue) return super.binop(kind, other, context, node);
|
|
|
| switch (kind) {
|
| @@ -1162,7 +1308,7 @@ class ObjectValue extends EvaluatedValue {
|
| }
|
|
|
| initFields() {
|
| - var allMembers = world.gen._orderValues(type.getAllMembers());
|
| + var allMembers = world.gen._orderValues(type.genericType.getAllMembers());
|
| for (var f in allMembers) {
|
| if (f.isField && !f.isStatic && f.declaringType.isClass) {
|
| fields[f] = f.computeValue();
|
| @@ -1220,7 +1366,7 @@ class ObjectValue extends EvaluatedValue {
|
| _code = buf.toString();
|
| }
|
|
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| if (other is! ObjectValue) return super.binop(kind, other, context, node);
|
|
|
| switch (kind) {
|
| @@ -1318,11 +1464,11 @@ class GlobalValue extends Value implements Comparable {
|
| */
|
| class BareValue extends Value {
|
| final bool isType;
|
| - final MethodGenerator home;
|
| + final CallingContext home;
|
|
|
| String _code;
|
|
|
| - BareValue(this.home, MethodGenerator outermost, SourceSpan span):
|
| + BareValue(this.home, CallingContext outermost, SourceSpan span):
|
| isType = outermost.isStatic,
|
| super(outermost.method.declaringType, null, span);
|
|
|
| @@ -1336,7 +1482,7 @@ class BareValue extends Value {
|
| if (_code === null) _code = isType ? type.jsname : home._makeThisCode();
|
| }
|
|
|
| - MemberSet _tryResolveMember(MethodGenerator context, String name, bool isDynamic, Node node) {
|
| + MemberSet _tryResolveMember(CallingContext context, String name, Node node) {
|
| assert(context == home);
|
|
|
| // TODO(jimhug): Confirm this matches final resolution of issue 641.
|
| @@ -1349,7 +1495,7 @@ class BareValue extends Value {
|
| }
|
|
|
| _ensureCode();
|
| - return super._tryResolveMember(context, name, isDynamic, node);
|
| + return super._tryResolveMember(context, name, node);
|
| }
|
| }
|
|
|
| @@ -1411,8 +1557,6 @@ class ConvertedValue extends Value {
|
| Value _tryUnion(Value right) => Value.union(value, right);
|
|
|
| // TODO(jmessery): override get/set/invoke/unop/binop?
|
| - // (The tricky part is we want them to use our staticType for warning
|
| - // purposes. It's like the whole ConcreteType/ConcreteMember issues...)
|
| }
|
|
|
| /**
|
| @@ -1461,13 +1605,13 @@ class VariableValue extends Value {
|
| new VariableValue(staticType, code, span, isFinal, v);
|
|
|
| // TODO(jmesserly): anything else to override?
|
| - Value unop(int kind, MethodGenerator context, var node) {
|
| + Value unop(int kind, CallingContext context, var node) {
|
| if (value != null) {
|
| return replaceValue(value.unop(kind, context, node));
|
| }
|
| return super.unop(kind, context, node);
|
| }
|
| - Value binop(int kind, var other, MethodGenerator context, var node) {
|
| + Value binop(int kind, var other, CallingContext context, var node) {
|
| if (value != null) {
|
| return replaceValue(value.binop(kind, _unwrap(other), context, node));
|
| }
|
|
|