| OLD | NEW |
| 1 /** | 1 /** |
| 2 * A brief description of some nodes. | 2 * A brief description of some nodes. |
| 3 * | 3 * |
| 4 * Scope block information: | 4 * Scope block information: |
| 5 * variables (Variable[]): a list of variables declared in the block | 5 * variables (Variable[]): a list of variables declared in the block |
| 6 * functions (Function[]): a list of functions declared in the block | 6 * functions (Function[]): a list of functions declared in the block |
| 7 * constants (Variable[]): a list of constants declared in the block | 7 * constants (Variable[]): a list of constants declared in the block |
| 8 * classes (Class[]): a list of classes declared in the block | 8 * classes (Class[]): a list of classes declared in the block |
| 9 * objects (Class[]): a list of objects declared in the block | 9 * objects (Class[]): a list of objects declared in the block |
| 10 * code (Statement[]): a list of statements in the block | 10 * code (Statement[]): a list of statements in the block |
| 11 */ | 11 */ |
| 12 | 12 |
| 13 /** | 13 /** |
| 14 * Takes the node rooted at the AST and decomposes it into readable sections. | 14 * Takes the node rooted at the AST and decomposes it into readable sections. |
| 15 */ | 15 */ |
| 16 function clean_ast(ast) { | 16 function clean_ast(ast) { |
| 17 assert(ast.type == TOK_LC); | 17 assert(ast.type == TOK_LC); |
| 18 let info = { | 18 let info = { |
| 19 variables: [], | 19 variables: [], |
| 20 constants: [], | 20 constants: [], |
| 21 objects: [], | 21 objects: [], |
| 22 classes: [], | 22 classes: [], |
| 23 functions: [], | 23 functions: [], |
| 24 code: [] | 24 code: [] |
| 25 }; | 25 }; |
| 26 | 26 |
| 27 for each (let statement in ast.kids) { | 27 for (let statement of ast.kids) { |
| 28 if (statement.op == JSOP_DEFVAR) { | 28 if (statement.op == JSOP_DEFVAR) { |
| 29 let ret = make_variables(statement); | 29 let ret = make_variables(statement); |
| 30 info.variables = info.variables.concat(ret.vars); | 30 info.variables = info.variables.concat(ret.vars); |
| 31 info.objects = info.objects.concat(ret.objs); | 31 info.objects = info.objects.concat(ret.objs); |
| 32 } else if (statement.op == JSOP_DEFCONST) { | 32 } else if (statement.op == JSOP_DEFCONST) { |
| 33 let ret = make_variables(statement); | 33 let ret = make_variables(statement); |
| 34 info.constants = info.constants.concat(ret.vars); | 34 info.constants = info.constants.concat(ret.vars); |
| 35 info.objects = info.objects.concat(ret.objs); | 35 info.objects = info.objects.concat(ret.objs); |
| 36 } else if (statement.type == TOK_FUNCTION) { | 36 } else if (statement.type == TOK_FUNCTION) { |
| 37 info.functions.push(make_function(statement)); | 37 info.functions.push(make_function(statement)); |
| 38 } else if (prototype_assign(statement)) { | 38 } else if (prototype_assign(statement)) { |
| 39 let obj = make_class(statement); | 39 let obj = make_class(statement); |
| 40 merge_class(info, obj); | 40 merge_class(info, obj); |
| 41 } else { | 41 } else { |
| 42 info.code.push(statement); | 42 info.code.push(statement); |
| 43 } | 43 } |
| 44 } | 44 } |
| 45 return info; | 45 return info; |
| 46 } | 46 } |
| 47 | 47 |
| 48 /** | 48 /** |
| 49 * Visits the AST using the given function as a parameter. | 49 * Visits the AST using the given function as a parameter. |
| 50 * The parameter will take in a single argument, the AST node. | 50 * The parameter will take in a single argument, the AST node. |
| 51 */ | 51 */ |
| 52 function visit(root_ast, func, to_expand) { | 52 function visit(root_ast, func, to_expand) { |
| 53 function v_r(ast, func) { | 53 function v_r(ast, func) { |
| 54 if (ast == null) | 54 if (ast == null) |
| 55 return; | 55 return; |
| 56 if (func(ast)) return; | 56 if (func(ast)) return; |
| 57 for each (let child in ast.kids) | 57 for (let child of ast.kids) |
| 58 v_r(child, func); | 58 v_r(child, func); |
| 59 } | 59 } |
| 60 | 60 |
| 61 function sanitize(ast) { | 61 function sanitize(ast) { |
| 62 if (ast == null) | 62 if (ast == null) |
| 63 return null; | 63 return null; |
| 64 if (ast.op == JSOP_NAME && ast.atom in to_expand) { | 64 if (ast.op == JSOP_NAME && ast.atom in to_expand) { |
| 65 ast = sanitize(to_expand[ast.atom]); | 65 ast = sanitize(to_expand[ast.atom]); |
| 66 ast.expanded = true; | 66 ast.expanded = true; |
| 67 } | 67 } |
| 68 let sanitized_ast = { kids: [] }; | 68 let sanitized_ast = { kids: [] }; |
| 69 for (let key in ast) { | 69 for (let key of ast) { |
| 70 if (key == 'kids') { | 70 if (key == 'kids') { |
| 71 for each (let kid in ast.kids) { | 71 for (let kid of ast.kids) { |
| 72 sanitized_ast.kids.push(sanitize(kid)); | 72 sanitized_ast.kids.push(sanitize(kid)); |
| 73 } | 73 } |
| 74 } else { | 74 } else { |
| 75 sanitized_ast[key] = ast[key]; | 75 sanitized_ast[key] = ast[key]; |
| 76 } | 76 } |
| 77 } | 77 } |
| 78 return sanitized_ast; | 78 return sanitized_ast; |
| 79 } | 79 } |
| 80 | 80 |
| 81 if (to_expand) | 81 if (to_expand) |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 } | 150 } |
| 151 } | 151 } |
| 152 } else { | 152 } else { |
| 153 info_list.classes = info_list.classes.concat(obj); | 153 info_list.classes = info_list.classes.concat(obj); |
| 154 } | 154 } |
| 155 } | 155 } |
| 156 function make_variables(var_root) { | 156 function make_variables(var_root) { |
| 157 assert(var_root.op == JSOP_DEFVAR || var_root.op == JSOP_DEFCONST); | 157 assert(var_root.op == JSOP_DEFVAR || var_root.op == JSOP_DEFCONST); |
| 158 let variables = []; | 158 let variables = []; |
| 159 let objects = []; | 159 let objects = []; |
| 160 for each (let name in var_root.kids) { | 160 for (let name of var_root.kids) { |
| 161 let v = { name: name.atom }; | 161 let v = { name: name.atom }; |
| 162 v.init = (name.kids.length > 0 ? name.kids[0] : null); | 162 v.init = (name.kids.length > 0 ? name.kids[0] : null); |
| 163 v.loc = get_location(var_root); | 163 v.loc = get_location(var_root); |
| 164 if (v.init && v.init.op == JSOP_NEWINIT && v.init.kids[0] && | 164 if (v.init && v.init.op == JSOP_NEWINIT && v.init.kids[0] && |
| 165 v.init.kids[0].type == TOK_COLON) | 165 v.init.kids[0].type == TOK_COLON) |
| 166 objects.push(make_object(v)); | 166 objects.push(make_object(v)); |
| 167 else | 167 else |
| 168 variables.push(v); | 168 variables.push(v); |
| 169 } | 169 } |
| 170 return { vars: variables, objs: objects }; | 170 return { vars: variables, objs: objects }; |
| 171 } | 171 } |
| 172 | 172 |
| 173 function make_object(stub) { | 173 function make_object(stub) { |
| 174 stub.variables = {}; | 174 stub.variables = {}; |
| 175 stub.functions = {}; | 175 stub.functions = {}; |
| 176 stub.getters = {}; | 176 stub.getters = {}; |
| 177 stub.setters = {}; | 177 stub.setters = {}; |
| 178 let ast = stub.init; | 178 let ast = stub.init; |
| 179 let proto = stub.init.op == JSOP_GETPROP && stub.init.atom == 'prototype'; | 179 let proto = stub.init.op == JSOP_GETPROP && stub.init.atom == 'prototype'; |
| 180 delete stub['init']; | 180 delete stub['init']; |
| 181 if (proto) { | 181 if (proto) { |
| 182 » stub.inherits = [ast.kids[0].atom]; | 182 stub.inherits = [ast.kids[0].atom]; |
| 183 » return stub; | 183 return stub; |
| 184 } | 184 } |
| 185 for each (let init in ast.kids) { | 185 for (let init of ast.kids) { |
| 186 if (init.type != TOK_COLON) { | 186 if (init.type != TOK_COLON) { |
| 187 dump_ast(init); | 187 dump_ast(init); |
| 188 } | 188 } |
| 189 assert(init.type == TOK_COLON); | 189 assert(init.type == TOK_COLON); |
| 190 if (init.kids[0].type == TOK_NAME) { | 190 if (init.kids[0].type == TOK_NAME) { |
| 191 let name = init.kids[0].atom; | 191 let name = init.kids[0].atom; |
| 192 let value = init.kids[1]; | 192 let value = init.kids[1]; |
| 193 if (init.op == JSOP_GETTER) | 193 if (init.op == JSOP_GETTER) |
| 194 stub.getters[name] = make_function(value); | 194 stub.getters[name] = make_function(value); |
| 195 else if (init.op == JSOP_SETTER) | 195 else if (init.op == JSOP_SETTER) |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 239 | 239 |
| 240 function assert(cmd) { | 240 function assert(cmd) { |
| 241 if (!cmd) { | 241 if (!cmd) { |
| 242 throw new Error("Assertion failed"); | 242 throw new Error("Assertion failed"); |
| 243 } | 243 } |
| 244 } | 244 } |
| 245 | 245 |
| 246 function get_location(ast_node) { | 246 function get_location(ast_node) { |
| 247 return { line: ast_node.line, column: ast_node.column }; | 247 return { line: ast_node.line, column: ast_node.column }; |
| 248 } | 248 } |
| OLD | NEW |