| 33 | const TL_COUNT = 30 |
| 34 | |
| 35 | class FunctionBytecodeGenerator { |
| 36 | constructor(ast, chunk) { |
| 37 | this.ast = ast; |
| 38 | this.chunk = chunk || new VMChunk(); |
| 39 | this.reservedRegisters = new Set() |
| 40 | this.outputRegister = this.randomRegister(); |
| 41 | |
| 42 | // for arithmetics and loading values |
| 43 | // binary expressions and member expressions need 4 TL each |
| 44 | // call expressions need 6 (too lazy to calculate actual value, this is just a guess) |
| 45 | this.available = {} |
| 46 | this.TLMap = {} |
| 47 | for (let i = 1; i <= TL_COUNT; i++) { |
| 48 | const regName = `TL${i}` |
| 49 | this[regName] = this.randomRegister(); |
| 50 | this.TLMap[this[regName]] = regName |
| 51 | this.available[regName] = true |
| 52 | } |
| 53 | log(new LogData(`Output register: ${this.outputRegister}`, 'accent', false)) |
| 54 | |
| 55 | // for variable contexts |
| 56 | // variables declared by the scope, array of array of variable names |
| 57 | // 0th element is the global scope, subsequent elements are nested scopes |
| 58 | this.activeScopes = [[]] |
| 59 | // variables that are currently in the active scope, map of variable name to array of registers, |
| 60 | // where the last element is the most recent register (active reference) |
| 61 | this.activeVariables = {} |
| 62 | this.takenLabels = new Set() |
| 63 | // labels that need to be resolved |
| 64 | this.processStack = { |
| 65 | loops: [], |
| 66 | vfunc: [], |
| 67 | switch: [] |
| 68 | } |
| 69 | // a bunch of stacks which contain the current relevant label for each context |
| 70 | this.contextLabels = { |
| 71 | loops: [], |
| 72 | vfunc: [], |
| 73 | switch: [] |
| 74 | } |
| 75 | this.activeLabels = [] |
| 76 | // like activeVariables but for functions |
| 77 | // contains important information such as the IP of the function, register map for the arguments, dependencies, etc. |
| 78 | this.activeVFunctions = {} |
| 79 | // for variables that are out of current scope but still accessible |
| 80 | // ie. by functions |
| 81 | this.dropDefers = {} |
| 82 | this.vfuncReferences = [] |
| 83 | |
| 84 | this.resolveExpression = resolveExpression.bind(this) |
| 85 | this.resolveBinaryExpression = resolveBinaryExpression.bind(this) |
| 86 | this.resolveLogicalExpression = resolveLogicalExpression.bind(this) |
| 87 | this.resolveMemberExpression = resolveMemberExpression.bind(this) |
| 88 | this.resolveCallExpression = resolveCallExpression.bind(this) |
| 89 | this.resolveObjectExpression = resolveObjectExpression.bind(this) |
| 90 | this.resolveArrayExpression = resolveArrayExpression.bind(this) |
| 91 | this.resolveNewExpression = resolveNewExpression.bind(this) |
| 92 | this.resolveUnaryExpression = resolveUnaryExpression.bind(this) |
nothing calls this directly
no outgoing calls
no test coverage detected