class fix, singletons added
This commit is contained in:
parent
5cbfbaaa74
commit
45da7bde29
38
lib/ast.js
38
lib/ast.js
|
|
@ -394,6 +394,34 @@ Cola.AST_Class = Cola.DEFNODE("Class", "name extends", {
|
|||
}
|
||||
}, Cola.AST_Scope);
|
||||
|
||||
Cola.AST_Singleton = Cola.DEFNODE("Singleton", "name", {
|
||||
$iscola: true,
|
||||
$documentation: "Base class for singletons",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolSingleton] the name of this singleton"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.name._walk(visitor);
|
||||
Cola.walk_body(this, visitor);
|
||||
});
|
||||
}
|
||||
}, Cola.AST_Scope);
|
||||
|
||||
Cola.AST_Injector = Cola.DEFNODE("Injector", "name", {
|
||||
$iscola: true,
|
||||
$documentation: "Base class for injectors",
|
||||
$propdoc: {
|
||||
name: "[AST_SymbolInjector] the name of this injector"
|
||||
},
|
||||
_walk: function(visitor) {
|
||||
return visitor._visit(this, function(){
|
||||
this.name._walk(visitor);
|
||||
Cola.walk_body(this, visitor);
|
||||
});
|
||||
}
|
||||
}, Cola.AST_Scope);
|
||||
|
||||
Cola.AST_Lambda = Cola.DEFNODE("Lambda", "name argnames uses_arguments", {
|
||||
$documentation: "Base class for functions",
|
||||
$propdoc: {
|
||||
|
|
@ -951,6 +979,16 @@ Cola.AST_SymbolClass = Cola.DEFNODE("SymbolClass", null, {
|
|||
$documentation: "Symbol defining a class",
|
||||
}, Cola.AST_SymbolDeclaration);
|
||||
|
||||
Cola.AST_SymbolSingleton = Cola.DEFNODE("SymbolSingleton", null, {
|
||||
$iscola: true,
|
||||
$documentation: "Symbol defining a singleton",
|
||||
}, Cola.AST_SymbolDeclaration);
|
||||
|
||||
Cola.AST_SymbolInjector = Cola.DEFNODE("SymbolInjector", null, {
|
||||
$iscola: true,
|
||||
$documentation: "Symbol defining an injector",
|
||||
}, Cola.AST_SymbolDeclaration);
|
||||
|
||||
Cola.AST_SymbolFunarg = Cola.DEFNODE("SymbolFunarg", "type", {
|
||||
$documentation: "Symbol naming a function argument",
|
||||
}, Cola.AST_SymbolVar);
|
||||
|
|
|
|||
114
lib/parse.js
114
lib/parse.js
|
|
@ -1200,6 +1200,12 @@ Cola.Parser.prototype.statement = Cola.Parser.embed_tokens(function() {
|
|||
case "class":
|
||||
return this.class_();
|
||||
|
||||
case "singleton":
|
||||
return this.singleton_();
|
||||
|
||||
case "injector":
|
||||
return this.injector_();
|
||||
|
||||
case "function":
|
||||
return this.function_(Cola.AST_Defun);
|
||||
|
||||
|
|
@ -1436,7 +1442,7 @@ Cola.Parser.prototype.for_in = function (init) {
|
|||
|
||||
Cola.Parser.prototype.class_ = function(){
|
||||
if(this.S.in_class)
|
||||
this.token_error(this.prev(), "You can't define class in other class.");
|
||||
this.token_error(this.prev(), "You can define class, singleton or injector only in root scope.");
|
||||
|
||||
this.S.in_class = true;
|
||||
|
||||
|
|
@ -1504,6 +1510,112 @@ Cola.Parser.prototype.class_ = function(){
|
|||
});
|
||||
};
|
||||
|
||||
Cola.Parser.prototype.singleton_ = function(){
|
||||
if(this.S.in_class)
|
||||
this.token_error(this.prev(), "You can define class, singleton or injector only in root scope.");
|
||||
|
||||
this.S.in_class = true;
|
||||
|
||||
var _this = this,
|
||||
name = this.is("name") ? this.as_symbol(Cola.AST_SymbolSingleton) : this.unexpected();
|
||||
|
||||
this.S.class_name = name.name;
|
||||
|
||||
return new Cola.AST_Singleton({
|
||||
name: name,
|
||||
body: (function(loop, labels){
|
||||
++_this.S.in_function;
|
||||
_this.S.in_directives = true;
|
||||
_this.S.in_loop = 0;
|
||||
_this.S.labels = [];
|
||||
|
||||
var tmp, a = _this.block_();
|
||||
|
||||
--_this.S.in_function;
|
||||
_this.S.in_loop = loop;
|
||||
_this.S.labels = labels;
|
||||
|
||||
var mconstr = false;
|
||||
a.forEach(function(member){
|
||||
if(member instanceof Cola.AST_Defun && member.name instanceof Cola.AST_SymbolDefun && member.name.name == _this.S.class_name){
|
||||
if(member.type != "dynamic")
|
||||
_this.token_error(member.start, "Constructor can't have returned type.");
|
||||
|
||||
if(member.mods.length != 0)
|
||||
_this.token_error(member.start, "Constructor can't have modificators.");
|
||||
|
||||
if(member.argnames.length)
|
||||
_this.token_error(member.start, "Singleton's and injector's constructor can't have arguments.");
|
||||
|
||||
if(mconstr)
|
||||
_this.token_error(member.start, "Main constructor can be defined only one time");
|
||||
|
||||
mconstr = true;
|
||||
} else if(member instanceof Cola.AST_Defun && member.name instanceof Cola.AST_Dot && member.mods.indexOf("static") != -1){
|
||||
_this.token_error(member.start, "Unexpected `static` modificator.");
|
||||
}
|
||||
});
|
||||
|
||||
_this.S.in_class = false;
|
||||
_this.S.class_name = false;
|
||||
return a;
|
||||
})(this.S.in_loop, this.S.labels)
|
||||
});
|
||||
};
|
||||
|
||||
Cola.Parser.prototype.injector_ = function(){
|
||||
if(this.S.in_class)
|
||||
this.token_error(this.prev(), "You can define class, singleton or injector only in root scope.");
|
||||
|
||||
this.S.in_class = true;
|
||||
|
||||
var _this = this,
|
||||
name = this.is("name") ? this.as_symbol(Cola.AST_SymbolInjector) : this.unexpected();
|
||||
|
||||
this.S.class_name = name.name;
|
||||
|
||||
return new Cola.AST_Injector({
|
||||
name: name,
|
||||
body: (function(loop, labels){
|
||||
++_this.S.in_function;
|
||||
_this.S.in_directives = true;
|
||||
_this.S.in_loop = 0;
|
||||
_this.S.labels = [];
|
||||
|
||||
var tmp, a = _this.block_();
|
||||
|
||||
--_this.S.in_function;
|
||||
_this.S.in_loop = loop;
|
||||
_this.S.labels = labels;
|
||||
|
||||
var mconstr = false;
|
||||
a.forEach(function(member){
|
||||
if(member instanceof Cola.AST_Defun && member.name instanceof Cola.AST_SymbolDefun && member.name.name == _this.S.class_name){
|
||||
if(member.type != "dynamic")
|
||||
_this.token_error(member.start, "Constructor can't have returned type.");
|
||||
|
||||
if(member.mods.length != 0)
|
||||
_this.token_error(member.start, "Constructor can't have modificators.");
|
||||
|
||||
if(mconstr)
|
||||
_this.token_error(member.start, "Main constructor can be defined only one time");
|
||||
|
||||
if(member.argnames.length)
|
||||
_this.token_error(member.start, "Singleton's and injector's constructor can't have arguments.");
|
||||
|
||||
mconstr = true;
|
||||
} else if(member instanceof Cola.AST_Defun && member.name instanceof Cola.AST_Dot && member.mods.indexOf("static") != -1){
|
||||
_this.token_error(member.start, "Unexpected `static` modificator.");
|
||||
}
|
||||
});
|
||||
|
||||
_this.S.in_class = false;
|
||||
_this.S.class_name = false;
|
||||
return a;
|
||||
})(this.S.in_loop, this.S.labels)
|
||||
});
|
||||
};
|
||||
|
||||
Cola.Parser.prototype.as_funcarg = function(splatedexist) {
|
||||
var name = this.as_symbol(Cola.AST_SymbolFunarg), type = name, argtype = 'positional', defval = new Cola.AST_Noop, required = true;
|
||||
|
||||
|
|
|
|||
339
lib/translate.js
339
lib/translate.js
|
|
@ -1475,8 +1475,11 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
newNode.push(pre_constructor);
|
||||
main_constructors.forEach(function(constr){
|
||||
constr.body.unshift(new Cola.AST_Call({
|
||||
expression : new Cola.AST_Dot({ expression: new Cola.AST_This, property: "pre_constructor" }),
|
||||
args : []
|
||||
expression : new Cola.AST_Dot({
|
||||
expression : new Cola.AST_Proto({ expression: node.name, property: "pre_constructor" }),
|
||||
property : "call"
|
||||
}),
|
||||
args : [new Cola.AST_This]
|
||||
}));
|
||||
constr.body[0] = new Cola.AST_SimpleStatement({
|
||||
body : constr.body[0]
|
||||
|
|
@ -1488,8 +1491,11 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
newNode.push(post_constructor);
|
||||
main_constructors.forEach(function(constr){
|
||||
constr.body.push(new Cola.AST_Call({
|
||||
expression : new Cola.AST_Dot({ expression: new Cola.AST_This, property: "post_constructor" }),
|
||||
args : []
|
||||
expression : new Cola.AST_Dot({
|
||||
expression : new Cola.AST_Proto({ expression: node.name, property: "post_constructor" }),
|
||||
property : "call"
|
||||
}),
|
||||
args : [new Cola.AST_This]
|
||||
}));
|
||||
constr.body[constr.body.length - 1] = new Cola.AST_SimpleStatement({
|
||||
body : constr.body[constr.body.length - 1]
|
||||
|
|
@ -1537,7 +1543,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
member.args.unshift(new Cola.AST_This);
|
||||
} else
|
||||
|
||||
if(member instanceof Cola.AST_SymbolRef && hmembers.indexOf(member.name) != -1 && node.extends){
|
||||
if(member instanceof Cola.AST_SymbolRef && hmembers.indexOf(member.name) != -1){
|
||||
if(member.name == "super"){
|
||||
with_super = true;
|
||||
member.name = "$uper";
|
||||
|
|
@ -1549,6 +1555,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
: new Cola.AST_This,
|
||||
property : member.name
|
||||
});
|
||||
|
||||
if(lvl == 1) flvl_this.push(member);
|
||||
} else
|
||||
|
||||
|
|
@ -1564,6 +1571,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
: new Cola.AST_This,
|
||||
property : member.name
|
||||
});
|
||||
|
||||
if(lvl == 1) flvl_this.push(member);
|
||||
}
|
||||
|
||||
|
|
@ -1601,6 +1609,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if(with_super){
|
||||
|
|
@ -1617,6 +1626,326 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){
|
|||
node = new Cola.AST_BlockStatement({ body: newNode });
|
||||
} else
|
||||
|
||||
/*
|
||||
singleton Test {
|
||||
|
||||
const int i = 123;
|
||||
|
||||
Test(){ // constructor
|
||||
alert("test");
|
||||
}
|
||||
|
||||
queryAll("ul li a").forEach((el) =>
|
||||
el.onclick = () => console.log("click")
|
||||
);
|
||||
|
||||
covert String method1() => console.log("method");
|
||||
|
||||
get getter() => i;
|
||||
set setter(int val) => console.log(val);
|
||||
|
||||
selfExample(){
|
||||
query("*").onclick = () => console.log(self);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
to
|
||||
|
||||
Test(){
|
||||
this.pre_constructor();
|
||||
|
||||
alert("test")
|
||||
|
||||
this.post_constructor();
|
||||
}
|
||||
|
||||
Test::pre_constructor(){
|
||||
const int this.i = 123;
|
||||
}
|
||||
|
||||
Test::post_constructor(){
|
||||
queryAll("ul li a").forEach((el) =>
|
||||
el.onclick = () => console.log("click")
|
||||
);
|
||||
}
|
||||
|
||||
covert String Test::method1() => console.log("method");
|
||||
|
||||
get Test::getter() => i;
|
||||
set Test::setter(int val) => console.log(val);
|
||||
|
||||
Test::selfExample(){
|
||||
var self = this;
|
||||
query("*").onclick = () => console.log(self);
|
||||
}
|
||||
|
||||
*/
|
||||
if(node instanceof Cola.AST_Singleton){
|
||||
var pre_constructor, post_constructor, main_constructors = [],
|
||||
is_pre = true, members = [], binder;
|
||||
|
||||
newNode = [];
|
||||
node.name = new Cola.AST_SymbolRef(node.name);
|
||||
|
||||
pre_constructor = new Cola.AST_Defun({
|
||||
mods : ["covert"],
|
||||
type : "dynamic",
|
||||
name : new Cola.AST_Proto({
|
||||
expression : new Cola.AST_SymbolDefun(node.name),
|
||||
property : "pre_constructor"
|
||||
}),
|
||||
argnames : [],
|
||||
body : []
|
||||
});
|
||||
|
||||
post_constructor = new Cola.AST_Defun({
|
||||
mods : ["covert"],
|
||||
type : "dynamic",
|
||||
name : new Cola.AST_Proto({
|
||||
expression : new Cola.AST_SymbolDefun(node.name),
|
||||
property : "post_constructor"
|
||||
}),
|
||||
argnames : [],
|
||||
body : []
|
||||
});
|
||||
|
||||
var has_main_constr = false;
|
||||
node.body.forEach(function(member){
|
||||
if(member instanceof Cola.AST_Defun && member.name instanceof Cola.AST_SymbolDefun && member.name.name == node.name.name){
|
||||
main_constructors.push(member);
|
||||
newNode.push(member);
|
||||
|
||||
has_main_constr = true;
|
||||
|
||||
is_pre = false;
|
||||
} else
|
||||
|
||||
if(member instanceof Cola.AST_Lambda && member.name instanceof Cola.AST_SymbolDefun){
|
||||
if(members.indexOf(member.name.name) == -1) members.push(member.name.name);
|
||||
member.name = new Cola.AST_Proto({
|
||||
expression : node.name,
|
||||
property : member.name.name
|
||||
});
|
||||
newNode.push(member);
|
||||
} else
|
||||
|
||||
if(member instanceof Cola.AST_Var && member.mods.indexOf("static") != -1){
|
||||
member.definitions.forEach(function(def){
|
||||
var texpr = def.name;
|
||||
|
||||
if(!(texpr instanceof Cola.AST_Symbol)){
|
||||
while(!(texpr.expression instanceof Cola.AST_Symbol || texpr.expression instanceof Cola.AST_Constant)) texpr = texpr.expression;
|
||||
}
|
||||
|
||||
if(def.name instanceof Cola.AST_Symbol && (def.value || member.mods.indexOf("covert") != -1)){
|
||||
newNode.push(new Cola.AST_VarDef({
|
||||
name : new Cola.AST_Dot({ expression: node.name, property: def.name.name }),
|
||||
value : def.value
|
||||
}));
|
||||
|
||||
member.mods.splice(member.mods.indexOf("static"), 1);
|
||||
|
||||
newNode[newNode.length - 1] = new Cola.AST_Var({
|
||||
type : member.type,
|
||||
mods : member.mods,
|
||||
definitions : [newNode[newNode.length - 1]]
|
||||
});
|
||||
} else
|
||||
|
||||
if((def.value || member.mods.indexOf("covert") != -1) && !(texpr.expression instanceof Cola.AST_This)){
|
||||
texpr.expression = new Cola.AST_Dot({ expression: node.name, property: texpr.expression.name });
|
||||
newNode.push(new Cola.AST_VarDef({
|
||||
name : def.name,
|
||||
value : def.value
|
||||
}));
|
||||
|
||||
member.mods.splice(member.mods.indexOf("static"), 1);
|
||||
|
||||
newNode[newNode.length - 1] = new Cola.AST_Var({
|
||||
type : member.type,
|
||||
mods : member.mods,
|
||||
definitions : [newNode[newNode.length - 1]]
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
else {
|
||||
if(member instanceof Cola.AST_Var)
|
||||
member.definitions.forEach(function(def){
|
||||
var texpr = def.name;
|
||||
|
||||
if(!(texpr instanceof Cola.AST_Symbol)){
|
||||
while(!(texpr.expression instanceof Cola.AST_Symbol || texpr.expression instanceof Cola.AST_Constant)) texpr = texpr.expression;
|
||||
texpr = texpr.expression;
|
||||
}
|
||||
|
||||
if(texpr instanceof Cola.AST_Symbol && !(texpr instanceof Cola.AST_This) && members.indexOf(texpr.name) == -1)
|
||||
members.push(texpr.name);
|
||||
});
|
||||
|
||||
if(is_pre) pre_constructor.body.push(member);
|
||||
else post_constructor.body.push(member);
|
||||
}
|
||||
});
|
||||
|
||||
if(!has_main_constr){
|
||||
newNode.unshift(new Cola.AST_Defun({
|
||||
mods : [],
|
||||
type : "dynamic",
|
||||
name : new Cola.AST_SymbolDefun(node.name),
|
||||
argnames : [],
|
||||
body : []
|
||||
}));
|
||||
|
||||
main_constructors.push(newNode[0]);
|
||||
}
|
||||
|
||||
if(pre_constructor.body.length != 0){
|
||||
newNode.push(pre_constructor);
|
||||
main_constructors.forEach(function(constr){
|
||||
constr.body.unshift(new Cola.AST_Call({
|
||||
expression : new Cola.AST_Dot({ expression: new Cola.AST_This, property: "pre_constructor" }),
|
||||
args : []
|
||||
}));
|
||||
constr.body[0] = new Cola.AST_SimpleStatement({
|
||||
body : constr.body[0]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if(post_constructor.body.length != 0){
|
||||
newNode.push(post_constructor);
|
||||
main_constructors.forEach(function(constr){
|
||||
constr.body.push(new Cola.AST_Call({
|
||||
expression : new Cola.AST_Dot({ expression: new Cola.AST_This, property: "post_constructor" }),
|
||||
args : []
|
||||
}));
|
||||
constr.body[constr.body.length - 1] = new Cola.AST_SimpleStatement({
|
||||
body : constr.body[constr.body.length - 1]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var scope, lvl = 0, hmembers, with_self = false, self_def = false, flvl_this = [];
|
||||
binder = new Cola.TreeTransformer(function(member){
|
||||
var tmembers, tscope, tlvl, tself_def;
|
||||
member = member.clone();
|
||||
|
||||
if(lvl > 1 && member instanceof Cola.AST_Var){
|
||||
member.definitions.forEach(function(def){
|
||||
if(def.name instanceof Cola.AST_Symbol){
|
||||
if(hmembers.indexOf(def.name.name) != -1)
|
||||
hmembers.splice(hmembers.indexOf(def.name.name), 1);
|
||||
if(def.name.name == "self")
|
||||
self_def = true;
|
||||
}
|
||||
});
|
||||
} else
|
||||
|
||||
if(lvl > 1 && (member instanceof Cola.AST_Defun || member instanceof Cola.AST_Getter || member instanceof Cola.AST_Setter) && member.name instanceof Cola.AST_Symbol && hmembers.indexOf(member.name.name) != -1){
|
||||
hmembers.splice(hmembers.indexOf(member.name.name), 1);
|
||||
} else
|
||||
|
||||
if(member instanceof Cola.AST_Scope)
|
||||
scope = (lvl++, member);
|
||||
else
|
||||
|
||||
if(member instanceof Cola.AST_SymbolRef && hmembers.indexOf(member.name) != -1){
|
||||
|
||||
member = new Cola.AST_Dot({
|
||||
expression : lvl > 1
|
||||
? (with_self = true, new Cola.AST_SymbolRef({ name: "self" }))
|
||||
: new Cola.AST_This,
|
||||
property : member.name
|
||||
});
|
||||
|
||||
if(lvl == 1) flvl_this.push(member);
|
||||
} else
|
||||
|
||||
if(member instanceof Cola.AST_SymbolRef && member.name == "self" && !self_def){
|
||||
with_self = true;
|
||||
} else
|
||||
|
||||
if(member instanceof Cola.AST_SymbolVar && scope.name instanceof Cola.AST_Proto && (scope.name.property == "pre_constructor" || scope.name.property == "post_constructor")
|
||||
&& hmembers.indexOf(member.name) != -1){
|
||||
member = new Cola.AST_Dot({
|
||||
expression : lvl > 1
|
||||
? (with_self = true, new Cola.AST_SymbolVar({ name: "self" }))
|
||||
: new Cola.AST_This,
|
||||
property : member.name
|
||||
});
|
||||
|
||||
if(lvl == 1) flvl_this.push(member);
|
||||
}
|
||||
|
||||
tscope = scope; tlvl = lvl; tmembers = hmembers.slice(); tself_def = self_def;
|
||||
member._descend(member, this);
|
||||
scope = tscope; lvl = tlvl; hmembers = tmembers; self_def = tself_def;
|
||||
|
||||
return member;
|
||||
});
|
||||
|
||||
newNode.forEach(function(member, i){
|
||||
lvl = 0;
|
||||
flvl_this = [];
|
||||
with_self = false;
|
||||
self_def = false;
|
||||
hmembers = members.slice();
|
||||
|
||||
if(member instanceof Cola.AST_Lambda){
|
||||
newNode[i] = member.transform(binder);
|
||||
newNode[i].mods ? newNode[i].mods.push("method") : (newNode[i].mods = ["method"]);
|
||||
|
||||
if(with_self) {
|
||||
newNode[i].body.unshift(new Cola.AST_Var({
|
||||
mods : [],
|
||||
type : "dynamic",
|
||||
definitions : [new Cola.AST_VarDef({
|
||||
type : "dynamic",
|
||||
name : new Cola.AST_SymbolVar({ name: "self" }),
|
||||
value : new Cola.AST_This
|
||||
})]
|
||||
}));
|
||||
|
||||
flvl_this.forEach(function(th){
|
||||
th.expression = new Cola.AST_SymbolRef({ name: "self" });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
newNode.push(new Cola.AST_Return({
|
||||
value : new Cola.AST_New({
|
||||
args : [],
|
||||
expression : node.name
|
||||
})
|
||||
}));
|
||||
//node = new Cola.AST_BlockStatement({ body: newNode });
|
||||
newNode = new Cola.AST_Function({
|
||||
type : node.name.name,
|
||||
body : newNode,
|
||||
argnames : []
|
||||
});
|
||||
|
||||
newNode = new Cola.AST_Call({
|
||||
args : [],
|
||||
expression : newNode
|
||||
});
|
||||
|
||||
node = new Cola.AST_Var({
|
||||
type : node.name.name,
|
||||
mods : [],
|
||||
definitions : [new Cola.AST_VarDef({
|
||||
type : node.name.name,
|
||||
name : new Cola.AST_SymbolVar(node.name),
|
||||
value : newNode
|
||||
})]
|
||||
});
|
||||
} else
|
||||
|
||||
/*
|
||||
func(String s, Number n:, Array list..., Boolean b = false, h: 123){
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user