function evalRules(scope) {
  return [// "_", function() { console.log(this.toString()); },
    "Function(name, fargs, body)", function(b) {
        var val = new FunctionValue(this);
        lookupValue("es5:Function").get('prototype').forEach(function(v) {
          val.fieldHint('__proto__', v);
        });
        val.fieldHint('prototype', new Value());
        if(b.name.value) {
          scope.declare(b.name.value, val);
        }
        handleFunction(val, scope, new Value());
        return this;
      },
    "VarDecls(vardecs)", function(b) {
        b.vardecs.each(
          "VarDeclInit(name, e)", function(b) {
              scope.declare(b.name.value);
              inferAllTypes(scope, b.e);
              var values = scope.inferValues(b.e);
              values.forEach(function(v) {
                scope.hint(b.name.value, v);
              });
            }, 
          "VarDecl(name)", function(b) {
              scope.declare(b.name.value);
            }
        );
        return this;
      },
    "Assign(PropAccess(e1, prop), e2)", function(b) {
        inferAllTypes(scope, b.e1);
        var vs = scope.inferValues(b.e1);
        inferAllTypes(scope,b.e2);
        var vs2 = scope.inferValues(b.e2);
        vs.forEach(function(v) {
          vs2.forEach(function(v2) {
            v.fieldHint(b.prop.value, v2);
          });  
        });
        return this;
      },
    "Assign(Var(name), e)", function(b) {
        inferAllTypes(scope,b.e);
        var vs = scope.inferValues(b.e);
        vs.forEach(function(v) {
          scope.hint(b.name.value, v);
        });
        return this;
      },
    "PropAccess(e, prop)", function(b) {
        inferAllTypes(scope, b.e);
        var vs = scope.inferValues(this);
        if(vs.length > 0) {
          return; // property is defined
        }
        // Apparently there's a property used in the code that
        // is defined elsewhere (or by some other means)
        // let's add it to the object
        vs = scope.inferValues(b.e);
        vs.forEach(function(v) {
          v.fieldHint(b.prop.value, new Value());
        });
        return this;
      },
    "Call(PropAccess(e, prop), args)", function(b) {
        // property access is called as a function, let's hint that
        inferAllTypes(scope, b.e);
        inferAllTypes(scope, b.args);
        var vs = scope.inferValues(b.e);
        vs.forEach(function(v) {
          v.fieldHint(b.prop.value, instantiate(lookupValue("es5:Function")));
        });
        return this;
      },
    "Return(e)", function(b) {
        inferAllTypes(scope, b.e);
        var vs = scope.inferValues(b.e);
        vs.forEach(function(v) {
          scope.hint('__return', v);
        });
        return this;
      },
    "Var(name)", function(b) {
        this.setAnnotation("scope", scope);
        var vs = scope.get(b.name.value);
        if(!vs) {
          scope.declare(b.name.value);
          scope.hint(b.name.value, new Value());
        }
        return this;
      },
    "This()", function() {
        this.setAnnotation("scope", scope);
        // NOTE: Probably something went wrong here, or using this pointer outside of function?
        var vs = scope.get('__this');
        if(!vs) {
          scope.declare('__this');
          scope.hint('__this', new Value());
        }
        return this;
      }
  ];
}
Returns an array of transformations that pin-point points in the 
Javascript program where values are assigned to variables and stores
them in the current scope. Var() nodes are attached their current scope
for later inference.