This model combines and extends the pragmatics and semantic parsing examples.

var makeObj = function() {
  return {blond: flip(0.5), nice: flip(0.5), tall: flip(0.5)}
}

var worldPrior = function(nObjLeft, meaningFn, worldSoFar, prevFactor) {
  var worldSoFar = worldSoFar==undefined ? [] : worldSoFar
  var prevFactor = prevFactor==undefined ? 0 : prevFactor
  if (nObjLeft==0) {
    factor(-prevFactor)
    return worldSoFar
  } else {
    var newObj = makeObj()
    var newWorld = worldSoFar.concat([newObj])
    var newFactor = meaningFn(newWorld)?0:-100
    factor(newFactor - prevFactor)
    return worldPrior(nObjLeft-1, meaningFn, newWorld, newFactor)
  }
}


var meaning = function(utterance) {
  return combineMeanings(filter(function(m){return !(m.sem==undefined)},
                                 map(lexicalMeaning, utterance.split(" "))))
}

var lexicalMeaning = function(word) {

  var wordMeanings = {

    "blond" : {
      sem: function(world){return function(obj){return obj.blond}},
      syn: {dir:'L', int:'NP', out:'S'} },

    "nice" : {
      sem: function(world){return function(obj){return obj.nice}},
      syn: {dir:'L', int:'NP', out:'S'} },

    "tall" : {
      sem: function(world){return function(obj){return obj.tall}},
      syn: {dir:'L', int:'NP', out:'S'} },

    "Bob" : {
      sem: function(world){return find(function(obj){return obj.name=="Bob"}, world)},
      syn: 'NP' },

    "some" : {
      sem: function(world){return function(P){return function(Q){return filter(Q, filter(P, world)).length>0}}},
      syn: {dir:'R',
            int:{dir:'L', int:'NP', out:'S'},
            out:{dir:'R',
                 int:{dir:'L', int:'NP', out:'S'},
                 out:'S'}} },

    "all" : {
      sem: function(world){return function(P){return function(Q){return filter(neg(Q), filter(P, world)).length==0}}},
      syn: {dir:'R',
            int:{dir:'L', int:'NP', out:'S'},
            out:{dir:'R',
                 int:{dir:'L', int:'NP', out:'S'},
                 out:'S'}} },

    "none" : {
      sem: function(world){return function(P){return function(Q){return filter(Q, filter(P, world)).length==0}}},
      syn: {dir:'R',
            int:{dir:'L', int:'NP', out:'S'},
            out:{dir:'R',
                 int:{dir:'L', int:'NP', out:'S'},
                 out:'S'}} }
  }

  var meaning = wordMeanings[word];
  return meaning == undefined?{sem: undefined, syn: ''}:meaning;
}

var neg = function(Q){
  return function(x){return !Q(x)}
}


//assume that both f and a will give their actual semantic value after being applied to a world. make a new meaning that passes on world arg.
var applyWorldPassing = function(f,a) {
  return function(w){return f(w)(a(w))}
}

var combineMeaning = function(meanings) {
  var possibleComb = canApply(meanings,0)
  var i = possibleComb[randomInteger(possibleComb.length)]
  var s = meanings[i].syn
  if (s.dir == 'L') {
    var f = meanings[i].sem
    var a = meanings[i-1].sem
    var newmeaning = {sem: applyWorldPassing(f,a), syn: s.out}
    return meanings.slice(0,i-1).concat([newmeaning]).concat(meanings.slice(i+1))
  }
  if (s.dir == 'R') {
    var f = meanings[i].sem
    var a = meanings[i+1].sem
    var newmeaning = {sem: applyWorldPassing(f,a), syn: s.out}
    return meanings.slice(0,i).concat([newmeaning]).concat(meanings.slice(i+2))
  }
}

//make a list of the indexes that can (syntactically) apply.
var canApply = function(meanings,i) {
  if(i==meanings.length){
    return []
  }
  var s = meanings[i].syn
  if (s.hasOwnProperty('dir')){ //a functor
    var a = ((s.dir == 'L')?syntaxMatch(s.int, meanings[i-1].syn):false) |
        ((s.dir == 'R')?syntaxMatch(s.int, meanings[i+1].syn):false)
    if(a){return [i].concat(canApply(meanings,i+1))}
  }
  return canApply(meanings,i+1)
}


// The syntaxMatch function is a simple recursion to
// check if two syntactic types are equal.
var syntaxMatch = function(s,t) {
  return !s.hasOwnProperty('dir') ? s==t :
  s.dir==t.dir & syntaxMatch(s.int,t.int) & syntaxMatch(s.out,t.out)
}


// Recursively do the above until only one meaning is
// left, return it's semantics.
var combineMeanings = function(meanings){
  return meanings.length==1 ? meanings[0].sem : combineMeanings(combineMeaning(meanings))
}


var utterancePrior = function() {
  var utterances = ["some of the blond people are nice",
                    "all of the blond people are nice",
                    "none of the blond people are nice"]
  var i = randomInteger(utterances.length)
  return utterances[i]
}


var isall = function(world){
  return world.length==0 ? true : (world[0].blond?world[0].nice:true)&&isall(world.slice(1))
}

var literalListener = cache(function(utterance) {
  Infer({
    model() {
      var m = meaning(utterance)
      var world = worldPrior(2,m)
      factor(m(world)?0:-Infinity)
      return world
    }
  })
})

var speaker = cache(function(world) {
  Infer({
    model() {
      var utterance = utterancePrior()
      var L = literalListener(utterance)
      factor(L.score(world))
      return utterance
    }
  })
})


var listener = function(utterance) {
  Infer({
    model() {
      var world = worldPrior(2, function(w){return 1}) //use vacuous meaning to avoid any guide...
      //    var world = worldPrior(2, meaning(utterance)) //guide by literal meaning
      var S = speaker(world)
      factor(S.score(utterance))
      return isall(world)
    }
  })
}

// literalListener("some of the blond people are nice")
// speaker([{blond: true, nice: true, tall: false}])

viz(listener("some of the blond people are nice"))