heya-unify
Version:
Unify: a unification tool with a deep equivalence and partitioning of objects.
115 lines (101 loc) • 2.68 kB
JavaScript
/* UMD.define */ (typeof define=="function"&&define||function(d,f,m){m={module:module,require:require};module.exports=f.apply(null,d.map(function(n){return m[n]||require(n)}))})
(["module", "heya-ice/assert", "../main", "./walk"], function(module, ice, unify, walk){
"use strict";
ice = ice.specialize(module);
var empty = {};
function postArray(context){
var stackOut = context.stackOut, t = [];
for(var i = 0, s = this.s, l = s.length; i < l; ++i){
if(s.hasOwnProperty(i)){
t[i] = stackOut.pop();
}
}
stackOut.push(t);
}
function postObject(context){
var stackOut = context.stackOut, t = {}, s = this.s;
for(var k in s){
if(s.hasOwnProperty(k)){
t[k] = stackOut.pop();
}
}
stackOut.push(t);
}
function processObject(val, context){
if(val === unify._){
context.stackOut.push(s);
}else{
var stack = context.stack;
stack.push(new (walk.Command)(postObject, val));
for(var k in val){
if(val.hasOwnProperty(k)){
stack.push(val[k]);
}
}
}
}
var registry = [
walk.Command,
function processCommand(val, context){
val.f(context);
},
Array,
function processArray(val, context){
var stack = context.stack;
stack.push(new (walk.Command)(postArray, val));
for(var i = 0, l = val.length; i < l; ++i){
if(val.hasOwnProperty(i)){
stack.push(val[i]);
}
}
},
unify.Variable,
function processVariable(val, context){
var env = context.env;
if(val.bound(env)){
context.stack.push(val.get(env));
}else{
context.stackOut.push(val);
}
},
unify.Unifier,
function processAsValue(val, context){
context.stackOut.push(val);
},
Date,
function processDate(val, context){
context.stackOut.push(new Date(val.getTime()));
},
RegExp,
function processRegExp(val, context){
context.stackOut.push(new RegExp(val.source,
(val.global ? "g" : "") +
(val.multiline ? "m" : "") +
(val.ignoreCase ? "i" : "")
));
}
],
filters = [];
function processOther(val, context){
context.stackOut.push(val);
}
function clone(source, env, opt){
var stackOut = [];
opt = opt || empty;
var context = opt.context || {}, stackOut = [];
context.stackOut = stackOut;
context.env = env;
walk(source, {
processObject: opt.processObject || processObject,
processOther: opt.processOther || processOther,
registry: opt.registry || clone.registry,
filters: opt.filters || clone.filters,
context: context
});
ice.assert(stackOut.length == 1);
return stackOut[0];
}
clone.registry = registry;
clone.filters = filters;
return clone;
});