Functions features completed.

This commit is contained in:
Onoshko Dan 2014-04-28 03:30:25 +07:00
parent 3ce0b42fd7
commit 50ff6c272c
5 changed files with 616 additions and 133 deletions

View File

@ -233,7 +233,7 @@ ColaScript is a language that compiles in JavaScript. This language is similar t
print(str) => console.log(str);
- named arguments
- named arguments, status: done
hello(String name:) => console.log("Hello @name!");
hello(name: 'dangreen'); // Hello dangreen!
@ -241,13 +241,13 @@ ColaScript is a language that compiles in JavaScript. This language is similar t
hello(name: "World") => console.log("Hello @name!");
hello(); // Hello World!
- defaults for positional arguments
- defaults for positional arguments, status: done
hello(String name = "World!") => console.log("Hello @name!");
hello(String name = "World") => console.log("Hello @name!");
hello('dangreen'); // Hello dangreen!
hello(); // Hello World!
- some arguments into array
- some arguments into array, status: done
main(name, skills...){
console.log("My name is @name, my skills:");

View File

@ -391,6 +391,21 @@ Cola.AST_Defun = Cola.DEFNODE("Defun", "type", {
$documentation: "A function definition"
}, Cola.AST_Lambda);
Cola.AST_Namedarg = Cola.DEFNODE("Namedarg", "start end name value", {
$documentation: "Named argument",
$propdoc: {
value: "Value of named argument"
}
}, Cola.AST_SymbolRef);
Cola.AST_Defarg = Cola.DEFNODE("Defarg", "start end name type argtype defval", {
$documentation: "A function argument expression",
$propdoc: {
type: "Data type",
argtype: "positional/named/splated"
}
}, Cola.AST_SymbolFunarg);
/* -----[ JUMPS ]----- */
Cola.AST_Jump = Cola.DEFNODE("Jump", null, {

View File

@ -643,7 +643,9 @@ Cola.Tokenizer.prototype.handle_slash = function () {
Cola.Tokenizer.prototype.handle_dot = function () {
this.next();
if (!this.is_js && this.peek() == '.') return this.next(), this.token("punc", "..");
if (!this.is_js && this.peek() == '.' && this.peek(1) != ".") return this.next(), this.token("punc", "..");
else if (!this.is_js && this.peek() == '.' && this.peek(1) == ".") return this.next(), this.next(), this.token("punc", "...");
return Cola.is_digit(this.peek().charCodeAt(0))
? this.read_num(".")
: this.token("punc", ".");
@ -945,7 +947,7 @@ Cola.Parser.prototype.expect_token = function (type, val) {
Cola.Parser.prototype.expect = function (punc) { return this.expect_token("punc", punc); };
Cola.Parser.prototype.can_insert_semicolon = function () {
if(!this.is_js) return false; // ColaScript
if(!this.is_js) return false;
return !this.options.strict && (
this.S.token.nlb || this.is("eof") || this.is("punc", "}")
);
@ -1021,7 +1023,6 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
}
this.restoreS();
if(isfun) return this.function_(Cola.AST_Defun);
}
@ -1221,10 +1222,39 @@ Cola.Parser.prototype.for_in = function (init) {
});
};
Cola.Parser.prototype.as_funcarg = function(splatedexist) {
var name = this.as_symbol(Cola.AST_SymbolFunarg), type = name, argtype = 'positional', defval = new Cola.AST_Noop();
if(this.is("name")) name = this.as_symbol(Cola.AST_SymbolFunarg);
if(this.is("punc", "...")){
if(splatedexist) this.token_error(this.S, "Unexpected token: splated argument can be only one.");
if(type != name && type.name != "Array") this.token_error(this.S, "Unexpected token: splated argument must have `Array` type.");
this.next();
argtype = "splated";
} else if(this.is("operator", "=")){
this.next();
defval = this.expression(false);
} else if(this.is("punc",":")){
this.next();
argtype = "named";
if(!this.is("punc",",") && !this.is("punc",")")){
defval = this.expression(false);
}
}
return new Cola.AST_Defarg({
name : name,
type : argtype == "splated" ? "Array" : type == name ? "dynamic" : type.name,
argtype : argtype,
defval : defval,
start : type.start,
end : this.prev()
});
};
Cola.Parser.prototype.function_ = function(ctor, type) {
!type && (type = "dynamic");
var in_statement = ctor === Cola.AST_Defun, _this = this;
var in_statement = ctor === Cola.AST_Defun, _this = this, splatedexist = false;
var name = this.is("name") ? this.as_symbol(in_statement ? Cola.AST_SymbolDefun : Cola.AST_SymbolLambda) : null;
if (in_statement && !name)
this.unexpected();
@ -1235,7 +1265,8 @@ Cola.Parser.prototype.function_ = function(ctor, type) {
argnames: (function(first, a){
while (!_this.is("punc", ")")) {
if (first) first = false; else _this.expect(",");
a.push(_this.as_symbol(Cola.AST_SymbolFunarg));
a.push(_this.is_js ? _this.as_symbol(Cola.AST_SymbolFunarg) : _this.as_funcarg(splatedexist));
splatedexist = a[a.length - 1].argtype == "splated";
}
_this.next();
return a;
@ -1511,7 +1542,7 @@ Cola.Parser.prototype.expr_atom = function(allow_calls) {
if (this.is("operator", "new")) {
return this.new_();
}
var start = this.S.token;
var type, start = this.S.token;
if (this.is("punc")) {
switch (start.value) {
case "(":
@ -1529,7 +1560,6 @@ Cola.Parser.prototype.expr_atom = function(allow_calls) {
isfun = (this.next(), (this.is('punc','{') || this.is('punc','=>')));
this.restoreS();
if(isfun) return this.function_(Cola.AST_Function);
}
@ -1546,6 +1576,30 @@ Cola.Parser.prototype.expr_atom = function(allow_calls) {
}
this.unexpected();
}
if (!this.is_js && this.is("name")) {
if(Cola.is_token(this.peek(), "name")){
type = this.S.token.value, this.next();
return this.function_(Cola.AST_Defun, type);
}
var _this = this, balance = 1, isfun = false;
this.dumpS();
this.next();
if(this.is('punc', '(')){
this.next();
this.next_until(function(){
if(_this.is('punc', '(')) balance++;
else if(_this.is('punc', ')')) balance--;
return balance == 0 || _this.is('eof');
});
isfun = (this.next(), (this.is('punc','{') || this.is('punc','=>')));
}
this.restoreS();
if(isfun) return this.function_(Cola.AST_Defun);
}
if (this.is("keyword", "function")) {
this.next();
var func = this.function_(Cola.AST_Function);
@ -1559,16 +1613,31 @@ Cola.Parser.prototype.expr_atom = function(allow_calls) {
this.unexpected();
};
Cola.Parser.prototype.expr_list = function (closing, allow_trailing_comma, allow_empty) {
var first = true, a = [];
Cola.Parser.prototype.expr_list = function (closing, allow_trailing_comma, allow_empty, allow_named_args) {
var first = true, a = [], name;
while (!this.is("punc", closing)) {
if (first) first = false; else this.expect(",");
if (allow_trailing_comma && this.is("punc", closing)) break;
if (this.is("punc", ",") && allow_empty) {
a.push(new Cola.AST_Hole({ start: this.S.token, end: this.S.token }));
} else {
a.push(this.expression(false));
}
} else
if(this.is("name") && allow_named_args){
name = Cola.$_cola_clone(this.S.token);
this.dumpS();
this.next();
if(this.is("punc",":")){
this.next();
a.push(new Cola.AST_Namedarg({
name : name.value,
value : this.expression(false),
start : name,
end : this.prev()
}));
} else {
this.restoreS();
a.push(this.expression(false))
}
} else a.push(this.expression(false));
}
this.next();
return a;
@ -1733,7 +1802,7 @@ Cola.Parser.prototype.subscripts = function(expr, allow_calls) {
return this.subscripts(new Cola.AST_Call({
start : start,
expression : expr,
args : this.expr_list(")"),
args : this.expr_list(")", false, false, !this.is_js),
end : this.prev()
}), true);
}

View File

@ -115,12 +115,29 @@ Cola.$_cola_array_asplice = function $_cola_array_asplice(_array, _from, _to, _a
}
Cola.$_cola_array_asplice.i = 8;
Cola.$_cola = Cola.$_cola_is + Cola.$_cola_isnt + Cola.$_cola_modulo + Cola.$_cola_isset + Cola.$_cola_isntset + Cola.$_cola_clone + Cola.$_cola_array_last + Cola.$_cola_array_range + Cola.$_cola_array_asplice;
Cola.$_cola_func_named_args = function $_cola_func_named_args(_args){
this.$ = _args;
}
Cola.$_cola_func_named_args.i = 9;
Cola.$_cola_func_set_named_args = function $_cola_func_set_named_args(_args){
if(_args[_args.length - 1] instanceof $_cola_func_named_args){
var nargs = [].pop.call(_args).$;
for(var i in nargs) if(nargs.hasOwnProperty(i))
_args[i] = nargs[i];
}
}
Cola.$_cola_func_set_named_args.i = 10;
Cola.$_cola =
Cola.$_cola_is + Cola.$_cola_isnt + Cola.$_cola_modulo + Cola.$_cola_isset +
Cola.$_cola_isntset + Cola.$_cola_clone + Cola.$_cola_array_last + Cola.$_cola_array_range +
Cola.$_cola_array_asplice + Cola.$_cola_func_named_args + Cola.$_cola_func_set_named_args;
Cola.Compressor.StdFuncs = {
$_cola_is : true,
$_cola_isnt : true,
$_cola_modulo : true,
$_cola_isset : true,
$_cola_is : true,
$_cola_isnt : true,
$_cola_modulo : true,
$_cola_isset : true,
$_cola_isntset : true
};

View File

@ -51,16 +51,29 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
var newNode, props = {}, parent = this.parent();
node = node.clone();
/*
main(){
console.log("hello world");
}
to
window.addEventListener('DOMContentLoaded',
function main(){
console.log("hello world");
}, false);
*/
if(options.main_binding && parent instanceof Cola.AST_Toplevel && node instanceof Cola.AST_Defun && node.name instanceof Cola.AST_SymbolDefun && node.name.name == "main"){
props = {
args : [new Cola.AST_String({ value : options.main_event }), node, new Cola.AST_False()]
args : [new Cola.AST_String({ value : options.main_event }), node, new Cola.AST_False()],
expression : new Cola.AST_Dot({
property : 'addEventListener',
//start : props.start,
//end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }),
expression : new Cola.AST_SymbolRef({ name : 'window' })
})
};
props.expression = new Cola.AST_Dot({
property : 'addEventListener',
//start : props.start,
//end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }),
expression : new Cola.AST_SymbolRef({ name : 'window' })
});
node = new Cola.AST_SimpleStatement({
body : new Cola.AST_Call(props),
@ -69,40 +82,64 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
});
} else
/*
5 ** 2
to
Math.pow(5, 2)
*/
if(node instanceof Cola.AST_Binary && node.operator == '**'){
props = {
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : 'Math' }),
end : node.left //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : 'Math' }),
end : node.left, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_Dot({
property : 'pow',
//start : props.start,
//end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }),
expression : new Cola.AST_SymbolRef({ name : 'Math' })
})
};
props.expression = new Cola.AST_Dot({
property : 'pow',
//start : props.start,
//end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'pow' }),
expression : new Cola.AST_SymbolRef({ name : 'Math' })
});
node = new Cola.AST_Call(props);
} else
/*
5 %% 2
to
$_cola_modulo(5, 2)
*/
if(node instanceof Cola.AST_Binary && node.operator == '%%'){
$_cola_hash[Cola.$_cola_modulo.i] = true;
props = {
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_modulo' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_modulo' }),
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_modulo'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_modulo'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
a ?= b;
to
if($_cola_isntset(a)) a = b;
*/
if(node instanceof Cola.AST_SimpleStatement && node.body instanceof Cola.AST_Assign && node.body.operator == '?='){
if(node.body.left instanceof Cola.AST_Sub && node.body.left.property instanceof Cola.AST_Noop){
props = {
@ -114,7 +151,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
props = {
operator : "-",
left : new Cola.AST_Dot(props),
right : new Cola.AST_Number({ value : 1})
right : new Cola.AST_Number({ value : 1 })
};
node.body.left.property = new Cola.AST_Binary(props);
@ -124,15 +161,15 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node.body.operator = '=';
props = {
args : [node.body.left]
args : [node.body.left],
//start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }),
//end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_isntset'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_isntset'
//start : props.start,
//end : props.start
});
node = new Cola.AST_If({
body : node.clone(),
@ -142,6 +179,14 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
});
} else
/*
func(a ?= b);
to
func($_cola_isntset(a) ? a = b : a);
*/
if(node instanceof Cola.AST_Assign && node.operator == '?='/* && !(parent instanceof Cola.AST_SimpleStatement)*/){
if(node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){
props = {
@ -163,15 +208,15 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node.operator = '=';
props = {
args : [node.left]
args : [node.left],
//start : new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isntset' }),
//end : new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_isntset'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_isntset'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Conditional({
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'punc', value : '(' }),
@ -182,89 +227,141 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
});
} else
/*
a ? b
to
$_cola_isset(a) ? a : b
*/
if(node instanceof Cola.AST_Conditional && node.alternative instanceof Cola.AST_Noop){
$_cola_hash[Cola.$_cola_isset.i] = true;
props = {
args : [node.condition],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.condition],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }),
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_isset'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_isset'
//start : props.start,
//end : props.start
});
node.alternative = node.consequent;
node.consequent = node.condition;
node.condition = new Cola.AST_Call(props);
} else
/*
123 is Number
to
$_cola_is(123, Number)
*/
if(node instanceof Cola.AST_Binary && node.operator == 'is'){
$_cola_hash[Cola.$_cola_is.i] = true;
props = {
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_is' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_is' }),
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_is'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_is'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
true isnt String
to
$_cola_isnt(true, String);
*/
if(node instanceof Cola.AST_Binary && node.operator == 'isnt'){
$_cola_hash[Cola.$_cola_isnt.i] = true;
props = {
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isnt' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.left, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isnt' }),
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_isnt'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_isnt'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
isset a
or
a??
to
$_cola_isset(a)
*/
if(node instanceof Cola.AST_UnaryPostfix && node.operator == '??' || node instanceof Cola.AST_UnaryPrefix && node.operator == 'isset'){
$_cola_hash[Cola.$_cola_isset.i] = true;
props = {
args : [node.expression],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.expression],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_isset' }),
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_isset'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_isset'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
a = clone b
to
a = $_cola_clone(b)
*/
if(node instanceof Cola.AST_UnaryPrefix && node.operator == 'clone'){
$_cola_hash[Cola.$_cola_clone.i] = true;
props = {
args : [node.expression],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_clone' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.expression],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_clone' }),
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
expression : new Cola.AST_SymbolRef({
name : '$_cola_clone'
//start : props.start,
//end : props.start
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_clone'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
arr[] = 123
to
arr.push(123)
*/
if(node instanceof Cola.AST_Assign && node.operator == "=" && node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){
props = {
property : "push",
@ -282,11 +379,17 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node = new Cola.AST_Call(props);
} else
/*
arr[] /= 2
to
arr[arr.length - 1] /= 2
*/
if(node instanceof Cola.AST_Assign && node.operator != "=" && node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_Noop){
props = {
property : "length",
//start : node.left.start,
//end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }),
expression : node.left.expression
};
props = {
@ -298,43 +401,61 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node.left.property = new Cola.AST_Binary(props);
} else
/*
func(arr[])
to
func($_cola_array_last(arr))
*/
if(node instanceof Cola.AST_Sub && node.property instanceof Cola.AST_Noop){
$_cola_hash[Cola.$_cola_array_last.i] = true;
props = {
args : [node.expression],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_array_last' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.expression],
start : node.start,
end : node.end,
expression : new Cola.AST_SymbolRef({
name : '$_cola_array_last'
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_array_last'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
arr[0..1] = 123
to
$_cola_array_asplice(arr, 0, 1, 123)
*/
if(node instanceof Cola.AST_Assign && node.operator == '=' && node.left instanceof Cola.AST_Sub && node.left.property instanceof Cola.AST_ArrayRange){
$_cola_hash[Cola.$_cola_array_asplice.i] = true;
props = {
args : [node.left.expression, node.left.property.from, node.left.property.to, node.right],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_array_last' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.left.expression, node.left.property.from, node.left.property.to, node.right],
start : node.start,
end : node.end,
expression : new Cola.AST_SymbolRef({
name : '$_cola_array_asplice'
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_array_asplice'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
func(arr[0..1])
to
func(arr.slice(0, 1 + 1))
*/
if(node instanceof Cola.AST_Sub && node.property instanceof Cola.AST_ArrayRange){
props = {
property : "slice",
//start : node.left.start,
//end : new Cola.AST_Token({ nlb : false, type : 'name', value : 'push' }),
expression : node.expression
};
props = {
@ -343,45 +464,293 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
left : node.property.to,
right : new Cola.AST_Number({ value : 1})
})],
start : node.start, //props.start,
end : node.end, //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' }),
start : node.start,
end : node.end,
expression : new Cola.AST_Dot(props)
};
node = new Cola.AST_Call(props);
} else
/*
[0..3]
to
$_cola_array_range(0, 3)
*/
if(node instanceof Cola.AST_ArrayRange){
$_cola_hash[Cola.$_cola_array_range.i] = true;
props = {
args : [node.from, node.to],
start : node.start, //new Cola.AST_Token({ nlb : false, type : 'name', value : '$_cola_clone' }),
end : node.end //new Cola.AST_Token({ nlb : false, type : 'punc', value : ')' })
args : [node.from, node.to],
start : node.start,
end : node.end,
expression : new Cola.AST_SymbolRef({
name : '$_cola_array_range'
})
};
props.expression = new Cola.AST_SymbolRef({
name : '$_cola_array_range'
//start : props.start,
//end : props.start
});
node = new Cola.AST_Call(props);
} else
/*
func(a, b, name : name, c)
to
func(a, b, c, new $_cola_func_named_args({ name : name }))
*/
if(node instanceof Cola.AST_Call){
props = {
properties : []
};
var delQueue = [];
node.args.forEach(function(val, i){
if(!(val instanceof Cola.AST_Namedarg)) return;
$_cola_hash[Cola.$_cola_func_named_args.i] = true;
delQueue.push(i);
props.properties.push(new Cola.AST_ObjectKeyVal({
key : val.name,
value : val.value,
start : val.start,
end : val.end
}));
});
if(delQueue.length != 0){
delQueue.reverse().forEach(function(val){
node.args.splice(val, 1);
});
props = {
args : [new Cola.AST_Object(props)],
start : node.start,
end : node.end,
expression : new Cola.AST_SymbolRef({
name : '$_cola_func_named_args'
})
};
node.args.push(new Cola.AST_New(props));
}
} else
/*
func(String s, Number n:, Array list..., Boolean b = false, h: 123){
}
to
function func(s){
$_cola_func_set_named_args(arguments);
var $_cola_i, list = 3 <= arguments.length ? [].slice.call(arguments, 1, $_cola_i = arguments.length - 1) : ($_cola_i = 2, []),
b = arguments[$_cola_i+0] !== undefiend ? arguments[$_cola_i+0] : false,
n = arguments.n,
h = arguments.h !== undefined ? arguments.h : 123;
}
*/
if((node instanceof Cola.AST_Function || node instanceof Cola.AST_Defun) && node.argnames.length != 0){
var posed = [], named = [], onfront = true, delQueue = [], pos = 0, splated, aftersplated = -1;
node.argnames.forEach(function(val, i){
if(val.argtype == "positional"){
if(val.defval instanceof Cola.AST_Noop && onfront) pos++, node.argnames[i] = val.name;
else {
onfront = false;
delQueue.push(i);
posed.push({ pos : pos++, val : val });
}
splated && splated.after++;
} else if(val.argtype == "named"){
delQueue.push(i);
named.push(val);
} else if(val.argtype == "splated"){
onfront = false;
delQueue.push(i);
splated = { pos : pos++, after : 0, val : val };
}
});
if(delQueue.length != 0)
delQueue.reverse().forEach(function(val){
node.argnames.splice(val, 1);
});
props = {
type : "dynamic",
definitions : []
};
posed.forEach(function(val, i){
var pos = val.pos; val = val.val;
if(splated && (pos - 1 == splated.pos || pos + 1 == splated.pos)){
aftersplated = 0;
props.definitions.push(new Cola.AST_VarDef({
name : new Cola.AST_SymbolRef({ name : '$_cola_i' }),
value : null
}));
props.definitions.push(new Cola.AST_VarDef({
name : splated.val.name,
value : new Cola.AST_Conditional({
condition : new Cola.AST_Binary({
operator : "<=",
left : new Cola.AST_Number({ value : splated.pos + splated.after + 1 }),
right : new Cola.AST_Dot({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : "length"
})
}),
consequent : new Cola.AST_Call({
expression : new Cola.AST_Dot({
property : "call",
expression : new Cola.AST_Dot({
property : "slice",
expression : new Cola.AST_Array({ elements : [] })
})
}),
args : [
new Cola.AST_SymbolRef({ name : 'arguments' }),
new Cola.AST_Number({ value : splated.pos }),
new Cola.AST_Assign({
operator : '=',
left : new Cola.AST_SymbolRef({ name : '$_cola_i' }),
right : new Cola.AST_Binary({
operator : '-',
left : new Cola.AST_Dot({
property : "length",
expression : new Cola.AST_SymbolRef({ name : 'arguments' })
}),
right : new Cola.AST_Number({ value : splated.after })
})
})
]
}),
alternative : new Cola.AST_Seq({
car : new Cola.AST_Assign({
operator : '=',
left : new Cola.AST_SymbolRef({ name : '$_cola_i' }),
right : new Cola.AST_Number({ value : splated.pos })
}),
cdr : new Cola.AST_Array({ elements : [] })
})
})
}));
splated = false;
}
if(val.defval instanceof Cola.AST_Noop) props.definitions.push(new Cola.AST_VarDef({
name : val.name,
value : new Cola.AST_Sub({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : aftersplated == -1
? new Cola.AST_Number({ value : pos })
: new Cola.AST_Binary({
operator : '+',
left : new Cola.AST_SymbolRef({ name : '$_cola_i' }),
right : new Cola.AST_Number({ value : aftersplated++ })
})
})
}));
else props.definitions.push(new Cola.AST_VarDef({
name : val.name,
value : new Cola.AST_Conditional({
condition : new Cola.AST_Binary({
operator : "!==",
left : new Cola.AST_Sub({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : aftersplated == -1
? new Cola.AST_Number({ value : pos })
: new Cola.AST_Binary({
operator : '+',
left : new Cola.AST_SymbolRef({ name : '$_cola_i' }),
right : new Cola.AST_Number({ value : aftersplated })
})
}),
right : new Cola.AST_SymbolRef({ name : 'undefined' })
}),
consequent : new Cola.AST_Sub({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : aftersplated == -1
? new Cola.AST_Number({ value : pos })
: new Cola.AST_Binary({
operator : '+',
left : new Cola.AST_SymbolRef({ name : '$_cola_i' }),
right : new Cola.AST_Number({ value : aftersplated++ })
})
}),
alternative : val.defval
})
}));
});
named.forEach(function(val, i){
if(val.defval instanceof Cola.AST_Noop) props.definitions.push(new Cola.AST_VarDef({
name : val.name,
value : new Cola.AST_Dot({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : val.name.name
})
}));
else props.definitions.push(new Cola.AST_VarDef({
name : val.name,
value : new Cola.AST_Conditional({
condition : new Cola.AST_Binary({
operator : "!==",
left : new Cola.AST_Dot({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : val.name.name
}),
right : new Cola.AST_SymbolRef({ name : 'undefined' })
}),
consequent : new Cola.AST_Dot({
expression : new Cola.AST_SymbolRef({ name : 'arguments' }),
property : val.name.name
}),
alternative : val.defval
})
}));
});
if(delQueue.length != 0 || named.length != 0) node.body.unshift(new Cola.AST_Var(props));
if(named.length != 0){
$_cola_hash[Cola.$_cola_func_named_args.i] = true;
$_cola_hash[Cola.$_cola_func_set_named_args.i] = true;
node.body.unshift(new Cola.AST_SimpleStatement({
body : new Cola.AST_Call({
args : [new Cola.AST_SymbolRef({ name : 'arguments' })],
expression : new Cola.AST_SymbolRef({ name : '$_cola_func_set_named_args' })
})
}));
}
} else
/*
"test @a @{b} {{c}}"
to
"test "+a+" "+b+" "+c
*/
if(node instanceof Cola.AST_StringTemplate){
newNode = new Cola.AST_Binary({
operator : '+',
left : node.body[0],
right : node.body[1]
//start : node.body[0].start,
//end : node.body[1].end
});
for(var i = 2; i < node.body.length; i++)
newNode = new Cola.AST_Binary({
operator : '+',
left : newNode,
right : node.body[i]
//start : newNode.start,
//end : node.body[i].end
});
newNode.start = node.start;
@ -390,6 +759,19 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
node = newNode;
} else
/*
/
([\w-\.]+)
@
((?:[\w]+\.)+)
([a-zA-Z]{2,4})
/
to
/([\w-\.]+)@((?:[\w]+\.)+)([a-zA-Z]{2,4})/
*/
if(node instanceof Cola.AST_RegExp && (node.value.indexOf('\n') != -1 || /\/[\w]*x[\w]*$/.test(node.value))){
node.value = node.value.replace(/[\r\n\s]/g,'').replace(/(\/[\w]*)x([\w]*$)/, '$1$2');
}