TypeChecker: vars, args and functions registration
This commit is contained in:
parent
fea0f353c7
commit
3a08d8ebce
|
|
@ -13,6 +13,7 @@
|
||||||
<script src="./mozilla-ast.js"></script>
|
<script src="./mozilla-ast.js"></script>
|
||||||
<script src="./translate.js"></script>
|
<script src="./translate.js"></script>
|
||||||
<script src="./std.js"></script>
|
<script src="./std.js"></script>
|
||||||
|
<script src="./typecheck.js"></script>
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|
@ -295,7 +296,7 @@ main();</textarea>
|
||||||
return stream.toString();
|
return stream.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
function Mangle(){
|
function Test(){
|
||||||
var ast;
|
var ast;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
@ -304,7 +305,7 @@ main();</textarea>
|
||||||
if(!isjs.checked) ast = ast.toJavaScript({ main_binding : mainbinding.checked });
|
if(!isjs.checked) ast = ast.toJavaScript({ main_binding : mainbinding.checked });
|
||||||
|
|
||||||
// 3. mangle
|
// 3. mangle
|
||||||
//ast.figure_out_scope();
|
ast.figure_out_scope();
|
||||||
//ast.compute_char_frequency();
|
//ast.compute_char_frequency();
|
||||||
//ast.mangle_names({ sort : true, toplevel : true });
|
//ast.mangle_names({ sort : true, toplevel : true });
|
||||||
|
|
||||||
|
|
|
||||||
156
lib/typecheck.js
156
lib/typecheck.js
|
|
@ -51,9 +51,9 @@
|
||||||
* AST_SymbolFunarg
|
* AST_SymbolFunarg
|
||||||
|
|
||||||
Levels of follow:
|
Levels of follow:
|
||||||
1 level: Simple types: String, Number, Boolean, Function.
|
1 level: Simple types: String, Number, Boolean, Function.
|
||||||
2 level: Arrays and Object ( Array<val_type>, Array<key_type, val_type> ).
|
2 level: Arrays and Object ( Array<val_type>, Array<key_type, val_type> ).
|
||||||
Deep-level: interfaces, classes, singletones.
|
Deep : interfaces, classes (prototypes), singletones.
|
||||||
|
|
||||||
Operations to check:
|
Operations to check:
|
||||||
* AST_Return
|
* AST_Return
|
||||||
|
|
@ -63,4 +63,152 @@
|
||||||
* AST_Binary
|
* AST_Binary
|
||||||
* AST_Conditional
|
* AST_Conditional
|
||||||
* AST_Assign
|
* AST_Assign
|
||||||
*/
|
|
||||||
|
Warnings:
|
||||||
|
* type mismatch
|
||||||
|
* redefinition of variable
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// TypedObject
|
||||||
|
|
||||||
|
Cola.TypedObject = function (name, vartype, isfunc) {
|
||||||
|
this.name = name;
|
||||||
|
this.vartype = vartype;
|
||||||
|
this.isfunc = isfunc;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TypeStorage
|
||||||
|
|
||||||
|
Cola.TypeStorage = function (parentStorage) {
|
||||||
|
this.parentStorage = parentStorage;
|
||||||
|
this.objs = [];
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeStorage.prototype.contains = function (name, isfunc) {
|
||||||
|
return this.objs.some(function(el){
|
||||||
|
return el.name == name && el.isfunc == isfunc;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeStorage.prototype.remove = function (name, isfunc) {
|
||||||
|
var pre = this.objs.length;
|
||||||
|
this.objs = this.objs.filter(function(el){
|
||||||
|
return !(el.name == name && el.isfunc == isfunc);
|
||||||
|
});
|
||||||
|
|
||||||
|
return pre != this.objs.length;
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeStorage.prototype.uniqueAdd = function (name, vartype, isfunc) {
|
||||||
|
if(!this.contains(name, isfunc)){
|
||||||
|
this.objs.push(new Cola.TypedObject(name, vartype, isfunc));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeStorage.prototype.owerwriteAdd = function (name, vartype, isfunc) {
|
||||||
|
var removed = this.remove(name, isfunc);
|
||||||
|
this.objs.push(new Cola.TypedObject(name, vartype, isfunc));
|
||||||
|
return removed;
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeStorage.prototype.get = function (name) {
|
||||||
|
var obj = false;
|
||||||
|
this.objs.some(function(el){
|
||||||
|
return el.name == name && (obj = el);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(!obj && this.parentStorage) obj = this.parentStorage.get(name);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// TypeChecker
|
||||||
|
|
||||||
|
Cola.TypeChecker = function (parentStorage, om) {
|
||||||
|
this.outputMode = om == undefined ? Cola.TypeChecker.WARNING : om;
|
||||||
|
this.storage = new Cola.TypeStorage(parentStorage, this.outputMode);
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeChecker.prototype.reg = function (def) {
|
||||||
|
if(def.forEach) def.forEach(function(d){
|
||||||
|
if(d instanceof Cola.AST_VarDef && !this.storage.uniqueAdd(d.name.name, d.type, false)){
|
||||||
|
this.printVarRedef(d.name.start);
|
||||||
|
this.storage.owerwriteAdd(d.name.name, d.type, false);
|
||||||
|
} else
|
||||||
|
if(d instanceof Cola.AST_SymbolFunarg) this.storage.owerwriteAdd(d.name, d.type, false);
|
||||||
|
}, this); else
|
||||||
|
if(def instanceof Cola.AST_Defun){
|
||||||
|
if(!this.storage.uniqueAdd(def.name.name, "Function", false)){
|
||||||
|
this.printFuncRedef(def.start);
|
||||||
|
this.storage.owerwriteAdd(def.name.name, "Function", false);
|
||||||
|
}
|
||||||
|
this.storage.owerwriteAdd(def.name.name, def.type, true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeChecker.prototype.printMessage = function (token, msg) {
|
||||||
|
switch(this.outputMode){
|
||||||
|
case Cola.TypeChecker.WARNING:
|
||||||
|
console.warn("TypeWarning: " + msg)
|
||||||
|
break;
|
||||||
|
case Cola.TypeChecker.ERROR:
|
||||||
|
throw new TypeError(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeChecker.prototype.printMism = function (token) {
|
||||||
|
this.printMessage(token, "type mismatch (line: " + token.line + ", col: " + token.col + ", pos: " + token.pos + ")");
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeChecker.prototype.printVarRedef = function (token) {
|
||||||
|
this.printMessage(token, "redefinition of variable (line: " + token.line + ", col: " + token.col + ", pos: " + token.pos + ")");
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeChecker.prototype.printFuncRedef = function (token) {
|
||||||
|
this.printMessage(token, "redefinition of function (line: " + token.line + ", col: " + token.col + ", pos: " + token.pos + ")");
|
||||||
|
};
|
||||||
|
|
||||||
|
Cola.TypeChecker.WARNING = 0;
|
||||||
|
Cola.TypeChecker.ERROR = 1;
|
||||||
|
Cola.TypeChecker.SILENT = 2;
|
||||||
|
|
||||||
|
|
||||||
|
// Checker function
|
||||||
|
|
||||||
|
Cola.AST_Toplevel.DEFMETHOD("check_types", function(options){
|
||||||
|
options = Cola.defaults(options, {
|
||||||
|
output_mode: Cola.TypeChecker.WARNING
|
||||||
|
});
|
||||||
|
|
||||||
|
var currScope = null, csDump = null,
|
||||||
|
tw = new Cola.TreeWalker(function(node, descend){
|
||||||
|
|
||||||
|
if (node instanceof Cola.AST_Scope) {
|
||||||
|
node.type_checker = new Cola.TypeChecker(node.parent_scope ? node.parent_scope.type_checker.storage : null, options.output_mode);
|
||||||
|
|
||||||
|
if (node instanceof Cola.AST_Defun) currScope.type_checker.reg(node);
|
||||||
|
if (node instanceof Cola.AST_Function || node instanceof Cola.AST_Defun) node.type_checker.reg(node.argnames);
|
||||||
|
|
||||||
|
csDump = currScope;
|
||||||
|
currScope = node;
|
||||||
|
descend();
|
||||||
|
currScope = csDump;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node instanceof Cola.AST_Var)
|
||||||
|
currScope.type_checker.reg(node.definitions);
|
||||||
|
//else
|
||||||
|
|
||||||
|
//if ()
|
||||||
|
|
||||||
|
descend();
|
||||||
|
});
|
||||||
|
this.walk(tw);
|
||||||
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user