Skip to content

Commit

Permalink
closes #77; implemented object slice
Browse files Browse the repository at this point in the history
  • Loading branch information
satyr committed Aug 9, 2011
1 parent adc5f97 commit 8248a0f
Show file tree
Hide file tree
Showing 14 changed files with 206 additions and 231 deletions.
214 changes: 101 additions & 113 deletions lib/ast.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
var Node, Negatable, Block, Atom, Literal, Var, Key, Index, Chain, Call, Clone, List, Obj, Prop, Arr, Op, Assign, Import, Of, Existence, Fun, Class, Super, Parens, Splat, Jump, Throw, Return, While, For, Try, Switch, Case, If, Label, JS, Util, UTILITIES, LEVEL_TOP, LEVEL_PAREN, LEVEL_LIST, LEVEL_COND, LEVEL_OP, LEVEL_CALL, PREC, TAB, ID, SIMPLENUM, _ref, __import = function(obj, src){
var Node, Negatable, Block, Atom, Literal, Var, Key, Index, Chain, Call, List, Obj, Prop, Arr, Op, Assign, Import, Of, Existence, Fun, Class, Super, Parens, Splat, Jump, Throw, Return, While, For, Try, Switch, Case, If, Label, JS, Util, UTILITIES, LEVEL_TOP, LEVEL_PAREN, LEVEL_LIST, LEVEL_COND, LEVEL_OP, LEVEL_CALL, PREC, TAB, ID, SIMPLENUM, _ref, __import = function(obj, src){
var own = {}.hasOwnProperty;
for (var key in src) if (own.call(src, key)) obj[key] = src[key];
return obj;
Expand Down Expand Up @@ -562,14 +562,18 @@ exports.Index = Index = (function(_super){
function _ctor(){} _ctor.prototype = prototype;
function Index(key, symbol){
var _this = new _ctor;
_this.key = key;
symbol || (symbol = '.');
switch (key.length) {
case 0:
_this.key = Key('__proto__');
key = Key('__proto__');
break;
case 1:
_this.key = key[0];
key = key[0];
break;
case void 8:
break;
default:
key = Arr(key);
}
if ('?' === symbol.charAt(0)) {
_this.soak = '?';
Expand All @@ -585,6 +589,7 @@ exports.Index = Index = (function(_super){
case '@':
_this.vivify = Arr;
}
_this.key = key;
_this.symbol = symbol;
return _this;
}
Expand Down Expand Up @@ -647,16 +652,17 @@ exports.Chain = Chain = (function(_super){
return this.tails.length || this.head.isComplex();
};
prototype.isCallable = function(){
if (this.tails.length) {
return !this.isArray();
var that, _ref;
if (that = (_ref = this.tails)[_ref.length - 1]) {
return !((_ref = that.key) != null ? _ref.items : void 8);
} else {
return this.head.isCallable();
}
};
prototype.isArray = function(){
var that, _ref;
if (that = (_ref = this.tails)[_ref.length - 1]) {
return (_ref = that.key) != null ? _ref.length : void 8;
return that.key instanceof Arr;
} else {
return this.head.isArray();
}
Expand Down Expand Up @@ -737,7 +743,7 @@ exports.Chain = Chain = (function(_super){
if (this.tails[0] instanceof Call && !this.head.isCallable()) {
this.carp('invalid callee');
}
this.expandArray(o);
this.expandSlice(o);
this.expandBind(o);
this.expandSplat(o);
this.expandStar(o);
Expand Down Expand Up @@ -864,26 +870,17 @@ exports.Chain = Chain = (function(_super){
}
}
};
prototype.expandArray = function(o){
var tails, i, tail, sub, ref, temps, j, key, items, _ref, _res, _len;
prototype.expandSlice = function(o){
var tails, i, tail, tailz, _ref;
tails = this.tails;
i = -1;
while (tail = tails[++i]) {
if ((_ref = tail.key) != null ? _ref.length : void 8) {
if ((_ref = tail.key) != null ? _ref.items : void 8) {
if (tails[i + 1] instanceof Call) {
tail.carp('calling an array');
}
_ref = Chain(this.head, tails.splice(0, i)).unwrap().cache(o), sub = _ref[0], ref = _ref[1], temps = _ref[2];
_res = [];
for (j = 0, _len = (_ref = tails.shift().key).length; j < _len; ++j) {
key = _ref[j];
_res.push(Chain(j ? ref : sub, [Index(key)]));
}
items = _res;
this.head = JS(Arr(items).compile(o));
if (temps) {
o.scope.free(temps[0]);
tail.carp('calling a slice');
}
tailz = tails.splice(0, i + 1);
this.head = tailz.pop().key.toSlice(o, Chain(this.head, tailz).unwrap());
i = -1;
}
}
Expand Down Expand Up @@ -956,25 +953,6 @@ exports.Call = Call = (function(_super){
};
return Call;
}(Node));
exports.Clone = Clone = (function(_super){
Clone.displayName = 'Clone';
var prototype = __extends(Clone, _super).prototype;
function _ctor(){} _ctor.prototype = prototype;
function Clone(base, mixins){
var _this = new _ctor;
_this.base = base;
_this.mixins = mixins;
return _this;
}
prototype.children = ['base', 'mixins'];
prototype.unfoldSoak = function(it){
return If.unfoldSoak(it, this, 'base');
};
prototype.compileNode = function(o){
return Import(Call.make(Util('clone'), [this.base]), Obj(this.mixins)).compile(o);
};
return Clone;
}(Node));
List = (function(_super){
List.displayName = 'List';
var prototype = __extends(List, _super).prototype;
Expand Down Expand Up @@ -1026,6 +1004,51 @@ exports.Obj = Obj = (function(_super){
return _this;
}
prototype.asObj = THIS;
prototype.toSlice = function(o, base, assign){
var items, i, node, ref, temps, name, chain, logic, key, val, _len, _ref;
items = this.items;
for (i = 0, _len = items.length; i < _len; ++i) {
node = items[i];
if (node.comment) {
items.splice(i--, 1);
}
}
items.length || this.carp('empty object slice');
if (items.length > 1) {
_ref = base.cache(o), base = _ref[0], ref = _ref[1], temps = _ref[2];
} else {
ref = base;
}
for (i = 0, _len = items.length; i < _len; ++i) {
node = items[i];
if (node instanceof Prop || node instanceof Splat) {
node[name = (_ref = node.children)[_ref.length - 1]] = chain = Chain(base, [Index(node[name].maybeKey())]);
} else {
if (logic = node.hasDefault()) {
node = node.first;
}
if (node instanceof Parens) {
_ref = node.cache(o, true), key = _ref[0], node = _ref[1];
if (assign) {
_ref = [node, key], key = _ref[0], node = _ref[1];
}
key = Parens(key);
} else {
key = node;
}
val = chain = Chain(base, [Index(node.maybeKey())]);
if (logic) {
val = (logic.first = val, logic);
}
items[i] = Prop(key, val);
}
base = ref;
}
if (temps) {
(chain.head = Var(temps[0])).temp = true;
}
return this;
};
prototype.compileNode = function(o){
var items, code, idt, dic, i, node, logic, rest, multi, key, val, _len;
items = this.items;
Expand Down Expand Up @@ -1127,6 +1150,31 @@ exports.Arr = Arr = (function(_super){
return _results;
}.call(this)));
};
prototype.toSlice = function(o, base){
var items, ref, temps, i, item, splat, chain, _ref, _len;
items = this.items;
if (items.length > 1) {
_ref = base.cache(o), base = _ref[0], ref = _ref[1], temps = _ref[2];
} else {
ref = base;
}
for (i = 0, _len = items.length; i < _len; ++i) {
item = items[i];
if (splat = item instanceof Splat) {
item = item.it;
}
if (item.isEmpty()) {
continue;
}
chain = Chain(base, [Index(item)]);
items[i] = splat ? Splat(chain) : chain;
base = ref;
}
if (chain && temps) {
(chain.head = Var(temps[0])).temp = true;
}
return this;
};
prototype.compile = function(o){
var items, code;
items = this.items;
Expand Down Expand Up @@ -1154,7 +1202,7 @@ exports.Op = Op = (function(_super){
var EQUALITY, COMPARER, prototype = __extends(Op, _super).prototype;
function _ctor(){} _ctor.prototype = prototype;
function Op(op, first, second, post){
var chain, node, _i, _ref, _len, _this = new _ctor;
var node, _i, _ref, _len, _this = new _ctor;
switch (op) {
case 'of':
return new Of(first, second);
Expand All @@ -1170,16 +1218,11 @@ exports.Op = Op = (function(_super){
first = Chain(first.it).add(Call([], true));
}
first.newed = true;
if ((chain = first.base || first) instanceof Chain) {
while (chain.head.base instanceof Chain) {
chain = chain.head.base;
}
for (_i = 0, _len = (_ref = chain.tails).length; _i < _len; ++_i) {
node = _ref[_i];
if (node instanceof Call && !node['new']) {
node['new'] = 'new';
return first;
}
for (_i = 0, _len = (_ref = first.tails || '').length; _i < _len; ++_i) {
node = _ref[_i];
if (node instanceof Call && !node['new']) {
node['new'] = 'new';
return first;
}
}
break;
Expand Down Expand Up @@ -1564,7 +1607,7 @@ exports.Assign = Assign = (function(_super){
prototype.compileNode = function(o){
var op, right, left, reft, lvar, sign, name, res, code, del, that, _ref;
op = this.op, right = this.right;
left = this.transleft(o).unwrap();
left = this.transleft(o);
if (left.isEmpty()) {
return (_ref = Parens(right), _ref.front = this.front, _ref.newed = this.newed, _ref).compile(o);
}
Expand Down Expand Up @@ -1729,68 +1772,13 @@ exports.Assign = Assign = (function(_super){
return _results;
};
prototype.transleft = function(o){
var left, base, items, sub, ref, i, node, logic, key, val, item, splat, _ref, _len;
left = this.left;
if (left instanceof Clone) {
base = left.base, items = left.mixins;
if (items.length > 1) {
_ref = base.cache(o), sub = _ref[0], ref = _ref[1], this.temps = _ref[2];
} else {
sub = ref = base;
}
for (i = 0, _len = items.length; i < _len; ++i) {
node = items[i];
base = i ? ref : sub;
if (node instanceof Prop) {
node.val = rechain(base, node.val);
} else {
if (logic = node.hasDefault()) {
node = node.first;
}
if (node instanceof Parens) {
_ref = node.cache(o, true), node = _ref[0], key = _ref[1];
key = Parens(key);
} else {
key = node;
}
val = Chain(base, [Index(node.maybeKey())]);
if (logic) {
val = (logic.first = val, logic);
}
items[i] = Prop(key, val);
}
}
return Obj(items);
}
if ((left = left.unwrap()) instanceof Chain && left.isArray()) {
items = left.tails.pop().key;
_ref = left.cache(o), sub = _ref[0], ref = _ref[1], this.temps = _ref[2];
for (i = 0, _len = items.length; i < _len; ++i) {
item = items[i];
if (splat = item instanceof Splat) {
item = item.it;
}
if (item instanceof Var) {
item = Parens(item);
}
item = rechain(i ? ref : sub, item);
items[i] = splat ? Splat(item) : item;
}
return Arr(items);
var left, _ref, _ref2;
left = this.left = this.left.unwrap();
if (left instanceof Chain && ((_ref = (_ref = left.tails)[_ref.length - 1]) != null ? (_ref2 = _ref.key) != null ? _ref2.items : void 8 : void 8)) {
return left.tails.pop().key.toSlice(o, left.unwrap(), true);
}
return left;
};
function rechain(head, tail){
var _ref;
if (tail.isEmpty()) {
return tail;
}
if (tail instanceof Obj) {
return Clone(head, tail.items);
} else {
return Chain(head, [(_ref = __clone(Index.prototype), _ref.key = tail.items || tail.maybeKey(), _ref)]);
}
}
return Assign;
}(Node));
exports.Import = Import = (function(_super){
Expand Down
4 changes: 2 additions & 2 deletions lib/grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -239,8 +239,8 @@ bnf = {
return L(Obj($2));
}), o('Chain ?', function(){
return Existence($1.unwrap());
}), o('Chain CLONE { Properties OptComma }', function(){
return Clone($1.unwrap(), $4);
}), o('Chain DOT { Properties OptComma }', function(){
return $1.add(Index(L(Obj($4)), $2));
})
],
Function: [
Expand Down
16 changes: 5 additions & 11 deletions lib/lexer.js
Original file line number Diff line number Diff line change
Expand Up @@ -549,24 +549,18 @@ exports.doLiteral = function(code, index){
}
break;
case '[':
this.closes.push(']');
this.adi();
break;
case ']':
case ')':
this.pair(val);
break;
case '{':
this.closes.push('}');
if (this.able()) {
this.token('CLONE', '');
}
this.adi();
this.closes.push(']}'.charAt(val === '{'));
break;
case '}':
if (this.inter && val !== (_ref = this.closes)[_ref.length - 1]) {
this.rest = code.slice(index + 1);
return 9e9;
}
// fallthrough
case ']':
case ')':
this.pair(val);
break;
case ':':
Expand Down
10 changes: 5 additions & 5 deletions lib/parser.js

Large diffs are not rendered by default.

Loading

0 comments on commit 8248a0f

Please sign in to comment.