switch done

This commit is contained in:
Onoshko Dan 2014-05-19 16:58:17 +07:00
parent dd22a18eb0
commit 3a8f96a40e
6 changed files with 219 additions and 37 deletions

View File

@ -104,12 +104,12 @@ ColaScript is a language that compiles in JavaScript. This language is similar t
## Expressions
- `switch` assignment
- `switch` assignment, status: done!
String weather = switch(temperature){
case -10: 'cold';
case 20: 'normal';
case 35: 'hot';
when -10: 'cold';
when 20: 'normal';
when 35: 'hot';
};
@ -314,4 +314,4 @@ ColaScript is a language that compiles in JavaScript. This language is similar t
### Statistic
- 33 features ( without classes )
- 29 done
- 30 done

View File

@ -505,6 +505,10 @@ Cola.AST_Case = Cola.DEFNODE("Case", "expression", {
}
}, Cola.AST_SwitchBranch);
Cola.AST_When = Cola.DEFNODE("When", null, {
$documentation: "A `when` switch branch"
}, Cola.AST_Case);
/* -----[ EXCEPTIONS ]----- */
Cola.AST_Try = Cola.DEFNODE("Try", "bcatch bfinally", {
@ -915,12 +919,17 @@ Cola.AST_String = Cola.DEFNODE("String", "value", {
}
}, Cola.AST_Constant);
Cola.AST_StringTemplate = Cola.DEFNODE("StringTemplate", null, {
Cola.AST_StringTemplate = Cola.DEFNODE("StringTemplate", "body", {
$documentation: "A string template",
$propdoc: {
body: "[AST_Statement*] the contents of this string template"
},
_walk: function(visitor) {
return visitor._visit(this, function(){
Cola.walk_body(this, visitor);
});
}
}, Cola.AST_Block);
}, Cola.AST_Statement);
Cola.AST_Number = Cola.DEFNODE("Number", "value", {
$documentation: "A number literal",

View File

@ -26,10 +26,17 @@
height: 100%;
}
.triple textarea {
width: 33.333%;
}
.double textarea {
width: 50%;
}
textarea {
-moz-box-sizing: border-box;
box-sizing: border-box;
width: 33.333%;
box-sizing: border-box;
height: 100%;
font-size: 15px;
float: left;
@ -75,7 +82,7 @@
</style>
</head>
<body>
<body class="triple">
<textarea id="source" onkeyup="compile()">// `main` functions may binding to a onload event
// Functions can defined without `function` keyword, with and without `type`
main(){
@ -203,6 +210,8 @@ main();</textarea>
<label for="is_js">js parser</label>
<input type="checkbox" id="main_binding" onclick="compile()">
<label for="main_binding">`main` binding</label>
<input type="checkbox" id="compressed" onclick="changeClass()">
<label for="compressed">compressed</label>
<span id="lenstat"></span>
</div>
</body>
@ -212,12 +221,19 @@ main();</textarea>
resultArea = document.getElementById("result"),
isjs = document.getElementById("is_js"),
mainbinding = document.getElementById("main_binding"),
compressed = document.getElementById("compressed"),
source;
if(!localStorage.source) localStorage.source = source = sourceArea.value;
else sourceArea.value = source = localStorage.source;
isjs.checked = localStorage.isjs == "t";
mainbinding.checked = localStorage.mainbinding == "t";
compressed.checked = localStorage.compressed == "t";
function changeClass(){
document.body.className = compressed.checked ? "triple" : "double";
localStorage.compressed = compressed.checked ? "t" : "f";
}
function compile(){
source = sourceArea.value;
@ -280,5 +296,6 @@ main();</textarea>
}
compile();
changeClass();
</script>
</html>

View File

@ -49,7 +49,7 @@
!this.Cola && (this.Cola = {});
Cola.KEYWORDS = 'break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with';
Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' clone isset is isnt class singleton injector';
Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' when clone isset is isnt class singleton injector';
Cola.KEYWORDS_ATOM = 'false null true';
Cola.cKEYWORDS_ATOM = Cola.KEYWORDS_ATOM + ' on yes off no';
@ -59,6 +59,7 @@ Cola.cRESERVED_WORDS = Cola.RESERVED_WORDS.replace(' class', '') + " " + Cola.cK
Cola.RESERVED_WORDS += " " + Cola.KEYWORDS_ATOM + " " + Cola.KEYWORDS;
Cola.KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
Cola.cKEYWORDS_BEFORE_EXPRESSION = Cola.KEYWORDS_BEFORE_EXPRESSION += ' when';
Cola.KEYWORDS = Cola.makePredicate(Cola.KEYWORDS);
Cola.cKEYWORDS = Cola.makePredicate(Cola.cKEYWORDS);
@ -70,6 +71,7 @@ Cola.KEYWORDS_ATOM = Cola.makePredicate(Cola.KEYWORDS_ATOM);
Cola.cKEYWORDS_ATOM = Cola.makePredicate(Cola.cKEYWORDS_ATOM);
Cola.KEYWORDS_BEFORE_EXPRESSION = Cola.makePredicate(Cola.KEYWORDS_BEFORE_EXPRESSION);
Cola.cKEYWORDS_BEFORE_EXPRESSION = Cola.makePredicate(Cola.cKEYWORDS_BEFORE_EXPRESSION);
Cola.OPERATOR_CHARS = Cola.makePredicate(Cola.characters("+-*&%=<>!?|~^"));
@ -271,11 +273,13 @@ Cola.Tokenizer = function ($TEXT, filename, is_js, html5_comments) {
this.KEYWORDS_ATOM = Cola.KEYWORDS_ATOM;
this.OPERATORS = Cola.OPERATORS;
this.UNARY_POSTFIX = Cola.UNARY_POSTFIX;
this.KEYWORDS_BEFORE_EXPRESSION = Cola.KEYWORDS_BEFORE_EXPRESSION;
} else {
this.KEYWORDS = Cola.cKEYWORDS;
this.KEYWORDS_ATOM = Cola.cKEYWORDS_ATOM;
this.OPERATORS = Cola.cOPERATORS;
this.UNARY_POSTFIX = Cola.cUNARY_POSTFIX;
this.KEYWORDS_BEFORE_EXPRESSION = Cola.cKEYWORDS_BEFORE_EXPRESSION;
}
this.is_js = !!is_js;
@ -351,7 +355,7 @@ Cola.Tokenizer.prototype.start_token = function () {
Cola.Tokenizer.prototype.token = function (type, value, is_comment) {
this.S.regex_allowed = ((type == "operator" && !this.UNARY_POSTFIX(value)) ||
(type == "keyword" && Cola.KEYWORDS_BEFORE_EXPRESSION(value)) ||
(type == "keyword" && this.KEYWORDS_BEFORE_EXPRESSION(value)) ||
(type == "punc" && Cola.PUNC_BEFORE_EXPRESSION(value)));
this.prev_was_dot = (type == "punc" && value == ".");
var ret = {
@ -930,7 +934,7 @@ Cola.Parser.prototype.prev = function () {
};
Cola.Parser.prototype.croak = function (msg, line, col, pos) {
var ctx = this.S.input.context();
var ctx = this.S ? this.S.input.context() : {};
Cola.js_error(msg,
ctx.filename,
line != null ? line : ctx.tokline,
@ -939,7 +943,7 @@ Cola.Parser.prototype.croak = function (msg, line, col, pos) {
};
Cola.Parser.prototype.token_error = function (token, msg) {
this.croak(msg, token.line, token.col);
this.croak(msg, token.line, token.col, token.pos);
};
Cola.Parser.prototype.unexpected = function (token) {
@ -1086,14 +1090,14 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
case "do":
return new Cola.AST_Do({
body : this.in_loop(function(){ return _this.statement() }),
body : this.in_loop(function(){ return this.statement() }),
condition : (this.expect_token("keyword", "while"), tmp = this.parenthesised(), this.semicolon(), tmp)
});
case "while":
return new Cola.AST_While({
condition : this.parenthesised(),
body : this.in_loop(function(){ return _this.statement() })
body : this.in_loop(function(){ return this.statement() })
});
case "for":
@ -1118,8 +1122,8 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
case "switch":
return new Cola.AST_Switch({
expression : this.parenthesised(),
body : this.in_loop(switch_body_)
expression : this.is('punc', '{') && !this.is_js ? new Cola.AST_Noop() : this.parenthesised(),
body : this.in_loop(this.switch_body_)
});
case "throw":
@ -1229,7 +1233,7 @@ Cola.Parser.prototype.regular_for = function (init) {
init : init,
condition : test,
step : step,
body : this.in_loop(function(){ return _this.statement() })
body : this.in_loop(function(){ return this.statement() })
});
};
@ -1242,7 +1246,7 @@ Cola.Parser.prototype.for_in = function (init) {
init : init,
name : lhs,
object : obj,
body : this.in_loop(function(){ return _this.statement() })
body : this.in_loop(function(){ return this.statement() })
});
};
@ -1353,10 +1357,10 @@ Cola.Parser.prototype.switch_body_ = function () {
var a = [], cur = null, branch = null, tmp;
while (!this.is("punc", "}")) {
if (this.is("eof")) this.unexpected();
if (this.is("keyword", "case")) {
if (this.is("keyword", "case") || !this.is_js && this.is("keyword", "when")) {
if (branch) branch.end = this.prev();
cur = [];
branch = new Cola.AST_Case({
branch = new (!this.is_js && this.is("keyword", "when") ? Cola.AST_When : Cola.AST_Case)({
start : (tmp = this.S.token, this.next(), tmp),
expression : this.expression(true),
body : cur
@ -1638,6 +1642,22 @@ Cola.Parser.prototype.expr_atom = function(allow_calls) {
func.end = this.prev();
return this.subscripts(func, allow_calls);
}
if (this.is("keyword", "switch") && !this.is_js) {
this.next();
var swtch = {
start : start,
expression : this.is('punc', '{') ? new Cola.AST_Noop() : this.parenthesised(),
body : this.in_loop(this.switch_body_),
end : this.prev()
}, _this = this;
swtch.body.forEach(function(branch){
if (branch.body.length > 1) _this.unexpected(branch.body[1].start);
else if (branch.body[0] && branch.body[0] instanceof Cola.AST_Var) _this.unexpected(branch.body[0].start);
});
return new Cola.AST_Switch(swtch);
}
if (Cola.ATOMIC_START_TOKEN[this.S.token.type]) {
return this.subscripts(this.as_atom_node(), allow_calls);
}
@ -2125,7 +2145,7 @@ Cola.Parser.prototype.expression = function(commas, no_in, in_dd) {
Cola.Parser.prototype.in_loop = function (cont) {
++this.S.in_loop;
var ret = cont();
var ret = cont.call(this);
--this.S.in_loop;
return ret;
};

View File

@ -66,7 +66,7 @@ Cola.$_cola_clone = function $_cola_clone(_item){
var result, types = [ Number, String, Boolean ];
for (var i in types)
if(types.hasOwnProperty(i) && _item instanceof types[i])
return type( _item );
return types[i]( _item );
if (_item.__proto__ === Array.prototype) {
result = [];

View File

@ -760,7 +760,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
;
to
fix: this and arguments objects
(function($_cola_expr, arguments){
$_cola_expr[0] = yes;
$_cola_expr.foo = bar;
@ -1043,6 +1043,8 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
if(node.body instanceof Cola.AST_Assign && (node.body.left instanceof Cola.AST_ArrayTemplate || node.body.left instanceof Cola.AST_ObjectTemplate ||
(node.body.left instanceof Cola.AST_Array || node.body.left instanceof Cola.AST_Object) && node.body.left.template) &&
node instanceof Cola.AST_SimpleStatement){
if(node.body.left.vardef && node.body.operator != "=") Cola.Parser.prototype.unexpected.call(Cola.Parser.prototype, node.body.left.start);
node = node.body;
var defs = [];
@ -1121,7 +1123,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
}));
el.splated = undefined;
defs.push(new Cola.AST_Assign({
operator : "=",
operator : node.operator,
left : el,
right : new Cola.AST_Conditional({
condition : new Cola.AST_Binary({
@ -1182,7 +1184,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
defs.push(el);
} else
if(el instanceof Cola.AST_SymbolRef || el instanceof Cola.AST_Sub || el instanceof Cola.AST_Dot) defs.push(new Cola.AST_Assign({
operator : "=",
operator : node.operator,
left : el,
right : new Cola.AST_Sub({
expression : symbol,
@ -1241,7 +1243,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
})
})); else
if(el.value instanceof Cola.AST_SymbolRef || el.value instanceof Cola.AST_Sub || el.value instanceof Cola.AST_Dot || el.value instanceof Cola.AST_Noop && el.start.type == "name") defs.push(new Cola.AST_Assign({
operator : "=",
operator : node.operator,
left : el.value instanceof Cola.AST_Noop ? new Cola.AST_SymbolRef({ name : el.key }) : el.value,
right : el.start.type == "name"
? new Cola.AST_Dot({
@ -1306,8 +1308,8 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
to
func((function($_cola_expr, arguments){
aname = obj.a;
bname = obj.b;
aname = $_cola_expr.a;
bname = $_cola_expr.b;
return $_cola_expr;
}).call(this, obj, arguments))
@ -1315,13 +1317,11 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
*/
if(node instanceof Cola.AST_Assign && (node.left instanceof Cola.AST_ArrayTemplate || node.left instanceof Cola.AST_ObjectTemplate ||
(node.left instanceof Cola.AST_Array || node.left instanceof Cola.AST_Object) && node.left.template)){
if(node.vardef) Cola.Parser.prototype.unexpected.call({}, node.start);
if(node.left.vardef) Cola.Parser.prototype.unexpected.call(Cola.Parser.prototype, node.start);
var defs = [];
var Symbol = node.right instanceof Cola.AST_SymbolRef
? node.right
: new Cola.AST_SymbolRef({ name : "$_cola_expr" });
var Symbol = new Cola.AST_SymbolRef({ name : "$_cola_expr" });
(function _rec(def, symbol, uid){
var skiped = false, k = 0, is_arrayt = def instanceof Cola.AST_Array || def instanceof Cola.AST_ArrayTemplate, _ = is_arrayt ? def.elements : def.properties;
@ -1336,7 +1336,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
}));
el.splated = undefined;
defs.push(new Cola.AST_Assign({
operator : "=",
operator : node.operator,
left : el,
right : new Cola.AST_Conditional({
condition : new Cola.AST_Binary({
@ -1384,7 +1384,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
}));
} else
if(el instanceof Cola.AST_SymbolRef || el instanceof Cola.AST_Sub || el instanceof Cola.AST_Dot) defs.push(new Cola.AST_Assign({
operator : "=",
operator : node.operator,
left : el,
right : new Cola.AST_Sub({
expression : symbol,
@ -1428,7 +1428,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
}
: function(el, j){
if(el.value instanceof Cola.AST_SymbolRef || el.value instanceof Cola.AST_Sub || el.value instanceof Cola.AST_Dot || el.value instanceof Cola.AST_Noop && el.start.type == "name") defs.push(new Cola.AST_Assign({
operator : "=",
operator : node.operator,
left : el.value instanceof Cola.AST_Noop ? new Cola.AST_SymbolRef({ name : el.key }) : el.value,
right : el.start.type == "name"
? new Cola.AST_Dot({
@ -1500,6 +1500,10 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
if(i == defs.length - 1) _(false);
});
props.body.push(new Cola.AST_Return({
value : new Cola.AST_SymbolRef({ name : "$_cola_expr" })
}));
props = {
expression : new Cola.AST_Function(props),
property : "call"
@ -1513,6 +1517,138 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
});
} else
/*
var o = switch {
case b < 10: f(b);
};
to
var o = (function(){
switch {
case b < 10: return f(b);
}
}).apply(this, arguments);
*/
if(node instanceof Cola.AST_Switch && !(parent instanceof Cola.AST_Block)){
node.body.forEach(function(branch){
if(!branch.body.length) return;
branch.body[0] = new Cola.AST_Return({
value : branch.body[0] instanceof Cola.AST_SimpleStatement ? branch.body[0].body : branch.body[0]
});
});
props = {
expression : new Cola.AST_Function({
type : "dynamic",
body : [node],
argnames : []
}),
property : "apply"
}
node = new Cola.AST_Call({
args : [new Cola.AST_SymbolRef({ name : "this" }), new Cola.AST_SymbolRef({ name : "arguments" })],
expression : new Cola.AST_Dot(props)
});
} else
/*
switch {
when b < 10: f(b);
case b < 15: y(b);
}
to
switch (false) {
when !(b < 10): f(b);
case !(b < 15): y(b);
}
*/
if(node instanceof Cola.AST_Switch && node.expression instanceof Cola.AST_Noop){
node.expression = new Cola.AST_False;
node.body.forEach(function(branch){
if(branch instanceof Cola.AST_Default) return;
if(branch.expression instanceof Cola.AST_Seq){
var seq = branch.expression;
while(true){
seq.car = new Cola.AST_UnaryPrefix({
operator : '!',
expression : seq.car
});
if(seq.cdr instanceof Cola.AST_Seq) seq = seq.cdr;
else {
seq.cdr = new Cola.AST_UnaryPrefix({
operator : '!',
expression : seq.cdr
});
break;
}
}
return;
}
branch.expression = new Cola.AST_UnaryPrefix({
operator : '!',
expression : branch.expression
});
});
} else
/*
switch {
when b < 10: f(b);
}
to
switch {
case b < 10:
f(b);
break;
}
*/
if(node instanceof Cola.AST_When){
node = new Cola.AST_Case(node);
node.body.push(new Cola.AST_Break);
}
/*
switch (g) {
case 11, 22: f(g);
}
to
switch (g) {
case 11: case 22: f(g);
}
*/
if(node instanceof Cola.AST_SwitchBranch && !(node instanceof Cola.AST_Default) && node.expression instanceof Cola.AST_Seq){
var branches = [], seq = node.expression;
while(true){
branches.push(new node.CTOR({ expression : seq.car, body : [] }));
if(seq.cdr instanceof Cola.AST_Seq) seq = seq.cdr;
else {
node.expression = seq.cdr
branches.push(node);
break;
}
}
node = branches;
}
/*
"test @a @{b} {{c}}"