Var and func def modificators.

covert int Math.some() => 123;

to

Object.defineProperty(Math, "some", {
    value: function some() {
        return 123;
    },
    writable: true
});
This commit is contained in:
Onoshko Dan 2014-08-16 13:21:45 +07:00
parent 1d297d9248
commit 8e3914de57
4 changed files with 215 additions and 50 deletions

View File

@ -397,6 +397,15 @@ Future plans
int index = -10;
arr[%index] = 34; // arr[index %% arr.length];
- var modificators. status: done
readonly int Math.Pi = 3.14;
list of modificators
* static: vars, funcs, getters and setters in class
* const: vars
* covert: vars, funcs, getters and setters in class and objects
- classes
class A {

View File

@ -404,7 +404,15 @@ Cola.AST_Function = Cola.DEFNODE("Function", "type", {
$documentation: "A function expression"
}, Cola.AST_Lambda);
Cola.AST_Defun = Cola.DEFNODE("Defun", "type", {
Cola.AST_Defun = Cola.DEFNODE("Defun", "type mods", {
$documentation: "A function definition"
}, Cola.AST_Lambda);
Cola.AST_Getter = Cola.DEFNODE("Getter", "type mods", {
$documentation: "A function definition"
}, Cola.AST_Lambda);
Cola.AST_Setter = Cola.DEFNODE("Setter", "type mods", {
$documentation: "A function definition"
}, Cola.AST_Lambda);
@ -589,7 +597,7 @@ Cola.AST_Definitions = Cola.DEFNODE("Definitions", "definitions", {
}
}, Cola.AST_Statement);
Cola.AST_Var = Cola.DEFNODE("Var", "type", {
Cola.AST_Var = Cola.DEFNODE("Var", "type mods", {
$documentation: "A `var` statement"
}, Cola.AST_Definitions);

View File

@ -49,13 +49,13 @@
!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', '') + ' when clone is isnt class singleton injector';
Cola.cKEYWORDS = Cola.KEYWORDS.replace(' void', '') + ' static covert get set when clone is isnt class singleton injector';
Cola.KEYWORDS_ATOM = 'false null true';
Cola.cKEYWORDS_ATOM = Cola.KEYWORDS_ATOM + ' on yes off no';
Cola.RESERVED_WORDS = 'abstract boolean byte char double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield';
Cola.cRESERVED_WORDS = Cola.RESERVED_WORDS.replace(' class', '') + " " + Cola.cKEYWORDS_ATOM + " " + Cola.cKEYWORDS;
Cola.cRESERVED_WORDS = Cola.RESERVED_WORDS.replace(' class', '').replace(' static', '') + " " + Cola.cKEYWORDS_ATOM + " " + Cola.cKEYWORDS;
Cola.RESERVED_WORDS += " " + Cola.KEYWORDS_ATOM + " " + Cola.KEYWORDS;
Cola.KEYWORDS_BEFORE_EXPRESSION = 'return new delete throw else case';
@ -768,6 +768,8 @@ Cola.cUNARY_PREFIX = Cola.makePredicate([
"+"
]);
Cola.cVARS_MODIFICATORS = Cola.makePredicate([ "const", "covert", "static" ]);
Cola.UNARY_POSTFIX = Cola.makePredicate([ "--", "++" ]);
Cola.cUNARY_POSTFIX = Cola.makePredicate([ "--", "++", "?" ]);
@ -1024,21 +1026,46 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
case "atom":
return this.simple_statement();
case "name":
if(!this.is_js && this.next_is("name")){
case "name": case "keyword":
var mods = [];
if(!this.is_js && this.is("keyword") && Cola.cVARS_MODIFICATORS(this.S.token.value))
while(this.is("keyword") && Cola.cVARS_MODIFICATORS(this.S.token.value)){
mods.push(this.S.token.value);
this.next();
}
if(!this.is_js && this.is("keyword", "var")){
this.next();
return tmp = this.var_(false, false, mods), this.semicolon(), tmp;
}
if(!this.is_js && this.is("name") && (this.next_is("name") || this.next_is("keyword", "function") || this.next_is("keyword", "get") || this.next_is("keyword", "set"))){
type = this.S.token.value, this.next();
var isfun = false;
var isfun = false, ctor = Cola.AST_Defun;
if(this.is("keyword", "get")){
ctor = Cola.AST_Getter;
this.next();
} else if(this.is("keyword", "set")){
cotr = Cola.AST_Setter;
this.next();
} else if(this.is("keyword", "function"))
this.next();
this.dumpS();
this.subscripts(this.as_symbol(Cola.AST_SymbolDefun), false);
isfun = this.is("punc", "(");
this.restoreS();
if(isfun) return this.function_(Cola.AST_Defun, type);
return tmp = this.var_(false, type), this.semicolon(), tmp;
if(isfun){
if(mods.indexOf("const") != -1) this.token_error(this.S.token, "Function can't have `const` modifer");
return this.function_(ctor, type, mods);
} else return tmp = this.var_(false, type, mods), this.semicolon(), tmp;
}
if(!this.is_js){
if(!this.is_js && this.is("name")){
var _this = this, balance = 1, isfun = false;
this.dumpS();
@ -1055,10 +1082,16 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
}
this.restoreS();
if(isfun) return this.function_(Cola.AST_Defun);
if(isfun) {
if(mods.indexOf("const") != -1) this.token_error(this.S.token, "Function can't have `const` modifer");
return this.function_(Cola.AST_Defun, false, mods);
}
}
return this.next_is("punc", ":")
if(!this.is_js && mods.length != 0 && this.is("name"))
return tmp = this.var_(false, false, mods), this.semicolon(), tmp;
if(this.is("name")) return this.next_is("punc", ":")
? this.labeled_statement()
: this.simple_statement();
@ -1132,7 +1165,7 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
this.next();
return new Cola.AST_EmptyStatement();
default:
this.unexpected();
if(!this.is_js && !this.is("keyword")) this.unexpected();
}
case "keyword":
@ -1165,6 +1198,12 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
case "function":
return this.function_(Cola.AST_Defun);
case "get":
if(!this.is_js) return this.function_(Cola.AST_Getter);
case "set":
if(!this.is_js) return this.function_(Cola.AST_Setter);
case "if":
return this.if_();
@ -1347,7 +1386,7 @@ Cola.Parser.prototype.as_funcarg = function(splatedexist) {
});
};
Cola.Parser.prototype.function_ = function(ctor, type) {
Cola.Parser.prototype.function_ = function(ctor, type, mods) {
!type && (type = "dynamic");
var in_statement = ctor === Cola.AST_Defun, _this = this, splatedexist = false;
@ -1357,6 +1396,7 @@ Cola.Parser.prototype.function_ = function(ctor, type) {
this.unexpected();
this.expect("(");
return new ctor({
mods: mods,
type: type,
name: name,
argnames: (function(first, a){
@ -1523,11 +1563,12 @@ Cola.Parser.prototype.vardefs = function (no_in, in_const, type) {
return a;
};
Cola.Parser.prototype.var_ = function(no_in, type) {
Cola.Parser.prototype.var_ = function(no_in, type, mods) {
(!type || type == "var") && (type = "dynamic");
return new Cola.AST_Var({
start : this.prev(),
definitions : this.vardefs(no_in, false, type),
mods : mods,
type : type,
end : this.prev()
});
@ -1907,7 +1948,7 @@ Cola.Parser.prototype.object_ = Cola.Parser.embed_tokens(function(is_template, i
ptype = name == "var" ? "dynamic" : name;
name = this.as_name();
} else ptype = false;
if (type == "name" && !this.is("punc", ":")) {
if ((type == "name" || !this.is_js && type == "keyword") && !this.is("punc", ":")) {
if (name == "get") {
if (!this.is_js && is_object === false) this.unexpected();
is_object = true;
@ -2253,7 +2294,7 @@ Cola.Parser.prototype.cascade = function(expr, start) {
|| last instanceof Cola.AST_Call
|| last instanceof Cola.AST_PropAccess
|| last instanceof Cola.AST_Array
)) this.unexpected();
)) this.unexpected(last.start);
}
if (!this.is("punc", "..")) break;
}

View File

@ -374,6 +374,111 @@ Cola.ContainCondAccess = function(node){
return false;
};
Cola.DefPropWithMods = function(def, mods){
if(mods.length == 0) return new Cola.AST_Assign({
start : def.start,
end : def.end,
operator : '=',
left : def.name,
right : def.value
});
if(mods.indexOf("static") != -1)
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, def.start, "Prop definition outside of class can't contain `static` modifer");
if(mods.indexOf("const") != -1 && !def.value)
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, def.start, "`const` prop can't have `undefined` value");
var dp = { properties : [
new Cola.AST_ObjectKeyVal({
key : "value",
value : def.value
})
] };
if(mods.indexOf("const") == -1)
dp.properties.push(new Cola.AST_ObjectKeyVal({
key : "writable",
value : new Cola.AST_True
}));
if(mods.indexOf("covert") == -1)
dp.properties.push(new Cola.AST_ObjectKeyVal({
key : "enumerable",
value : new Cola.AST_True
}));
return new Cola.AST_Call({
args : [
def.name.expression,
def.name instanceof Cola.AST_Sub
? def.name.property
: new Cola.AST_String({ value: def.name.property }),
new Cola.AST_Object(dp)],
expression : new Cola.AST_Dot({
expression : new Cola.AST_SymbolRef({ name: "Object" }),
property : "defineProperty"
})
});
};
Cola.DefFunWithMods = function(func, mods){
if(mods.length == 0) return new Cola.AST_Assign({
start : func.start,
end : func.end,
operator : '=',
left : func.name,
right : (function(node){
node.name = new Cola.AST_SymbolLambda({
start : node.name.start,
end : node.name.end,
name : node.name.property
});
return new Cola.AST_Function(node);
})(func)
});
if(mods.indexOf("static") != -1)
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, func.start, "Function definition outside of class can't contain `static` modifer");
var sname = func.name, dp = { properties : [
new Cola.AST_ObjectKeyVal({
key : "value",
value : (function(node){
node.name = new Cola.AST_SymbolLambda({
start : node.name.start,
end : node.name.end,
name : node.name.property
});
return new Cola.AST_Function(node);
})(func)
}),
new Cola.AST_ObjectKeyVal({
key : "writable",
value : new Cola.AST_True
})
] };
if(mods.indexOf("covert") == -1)
dp.properties.push(new Cola.AST_ObjectKeyVal({
key : "enumerable",
value : new Cola.AST_True
}));
return new Cola.AST_Call({
args : [
sname.expression,
sname instanceof Cola.AST_Sub
? sname.property
: new Cola.AST_String({ value: sname.property }),
new Cola.AST_Object(dp)],
expression : new Cola.AST_Dot({
expression : new Cola.AST_SymbolRef({ name: "Object" }),
property : "defineProperty"
})
});
};
Cola.AST_Toplevel.prototype.toJavaScript = function(options){
if(this.language == 'js') return this;
@ -941,43 +1046,53 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
} else
/*
int obj.num = 0
const int num = 1, obj.num = 0;
to
obj.num = 0
const num - 1;
Object.defineProperty(obj, "num", { value: 0, enumerable: true });
*/
if(node instanceof Cola.AST_Var){
var defCache = []; newNode = [];
node.definitions.forEach(function(def, i){
if(!(def.name instanceof Cola.AST_SymbolVar)){
if(def.name instanceof Cola.AST_SymbolVar){
if(!def.value)
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, def.start, "`const` var can't have `undefined` value");
defCache.push(def);
} else if(def.value){
if(defCache.length != 0){
newNode.push(node.clone());
newNode[newNode.length - 1].definitions = defCache;
defCache = [];
if(!node.mods || node.mods.length == 0 || node.mods.indexOf("const") != -1 && node.mods.length == 1){
newNode.push(node.mods.length == 1 ? new Cola.AST_Const(node) : node.clone());
newNode[newNode.length - 1].definitions = defCache;
defCache = [];
} else
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, node.start, "Var definition can contain only `const` modifer");
}
newNode.push(new Cola.AST_Assign({
start : def.start,
end : def.end,
operator : '=',
left : def.name,
right : def.value
}));
var texpr = def.name;
while(!(texpr.expression instanceof Cola.AST_SymbolVar)) texpr = texpr.expression;
texpr.expression = new Cola.AST_SymbolRef(texpr.expression);
newNode.push(Cola.DefPropWithMods(def, node.mods));
newNode[newNode.length - 1] = new Cola.AST_SimpleStatement({
body : newNode[newNode.length - 1]
});
} else defCache.push(def);
}
});
if(defCache.length != 0){
newNode.push(node.clone());
newNode[newNode.length - 1].definitions = defCache;
defCache = [];
if(!node.mods || node.mods.length == 0 || node.mods.indexOf("const") != -1 && node.mods.length == 1){
newNode.push(node.mods && node.mods.length == 1 ? new Cola.AST_Const(node) : node.clone());
newNode[newNode.length - 1].definitions = defCache;
defCache = [];
} else
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, node.start, "Var definition can contain only `const` modifer");
}
node = newNode;
@ -988,26 +1103,15 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
to
Math.rand = function(){}
Math.rand = function rand(){}
*/
if(node instanceof Cola.AST_Defun && !(node.name instanceof Cola.AST_SymbolDefun)){
var texpr = node.name;
while(!(texpr.expression instanceof Cola.AST_SymbolDefun)) texpr = texpr.expression;
texpr.expression = new Cola.AST_SymbolRef(texpr.expression);
node = new Cola.AST_Assign({
start : node.start,
end : node.end,
operator : '=',
left : node.name,
right : (function(node){
node.name = new Cola.AST_SymbolLambda({
start : node.name.start,
end : node.name.end,
name : node.name.property
});
return new Cola.AST_Function(node);
})(node)
});
node = Cola.DefFunWithMods(node, node.mods);
node = new Cola.AST_SimpleStatement({
body : node
});
@ -1074,6 +1178,9 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
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;
if(node.mods && node.mods.length != 0)
Cola.Parser.prototype.token_error.call(Cola.Parser.prototype, node.start, "Function definition outside of class can't contain any modifer");
node.argnames.forEach(function(val, i){
if(val.argtype == "positional"){
if(val.defval instanceof Cola.AST_Noop && onfront && !val.required) pos++, node.argnames[i] = val.name;
@ -1105,7 +1212,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
posed.forEach(function(val, i){
var pos = val.pos; val = val.val;
console.log(val);
if(val.argtype == "splated"){
aftersplated = 0;
props.definitions.push(new Cola.AST_VarDef({