Changeset 22778

Show
Ignore:
Timestamp:
11/05/08 20:51:22 (5 years ago)
Author:
fujidig
Message:

branches/source-convertをtrunkにマージ

Location:
lang/javascript/hsp-on-js
Files:
1 removed
3 modified

Legend:

Unmodified
Added
Removed
  • lang/javascript/hsp-on-js/trunk/src/compiler.js

    r22630 r22778  
    561561                        var constructorFinfoId = this.ax.prmsInfo[funcInfo.prmindex].offset; 
    562562                        var constructor = constructorFinfoId != -1 ? this.getUserDefFunc(constructorFinfoId) : null; 
    563                         return this.userDefFuncs[finfoId] = new Module(funcInfo.name, constructor, destructor, funcInfo.prmmax - 1); 
     563                        return this.userDefFuncs[finfoId] = new Module(funcInfo.name, constructor, destructor, funcInfo.prmmax - 1, finfoId); 
    564564                } 
    565565                var isCType = funcInfo.index == -2; // STRUCTDAT_INDEX_CFUNC 
     
    568568                        paramTypes[i] = this.ax.prmsInfo[funcInfo.prmindex + i].mptype; 
    569569                } 
    570                 return this.userDefFuncs[finfoId] = new UserDefFunc(isCType, funcInfo.name, this.labels[funcInfo.otindex], paramTypes); 
     570                return this.userDefFuncs[finfoId] = new UserDefFunc(isCType, funcInfo.name, this.labels[funcInfo.otindex], paramTypes, finfoId); 
    571571        }, 
    572572        compileFuncall: function compileFuncall(sequence) { 
  • lang/javascript/hsp-on-js/trunk/src/evaluator.js

    r22521 r22778  
    1818        this.strsize = new IntValue(0); 
    1919        this.random = new VCRandom(); 
     20         
     21        var mainLoop; 
     22        var literals = []; 
     23        var variables = this.variables; 
     24        var userDefFuncs = []; 
     25        this.evaluate = function evaluate() { 
     26                mainLoop = eval('(function mainLoop(self, stack, literals, variables, userDefFuncs) {\n' +  
     27                                this.createMainLoop(literals, userDefFuncs) + '\n})'); 
     28                try { 
     29                        mainLoop(this, this.stack, literals, variables, userDefFuncs); 
     30                } catch(e) { 
     31                        if(!(e instanceof HSPException)) { 
     32                                throw e; 
     33                        } 
     34                        this.disposeException(e); 
     35                } 
     36        }; 
     37        this.resume = function resume(callback) { 
     38                try { 
     39                        if(callback) callback(); 
     40                        this.pc ++; 
     41                        mainLoop(this, this.stack, literals, variables, userDefFuncs); 
     42                } catch(e) { 
     43                        if(!(e instanceof HSPException)) { 
     44                                throw e; 
     45                        } 
     46                        this.disposeException(e); 
     47                } 
     48        }; 
    2049} 
    2150 
     
    3463 
    3564Evaluator.prototype = { 
    36         evaluate: function evaluate() { 
    37                 try { 
    38                         while(true) { 
    39                                 var insn = this.sequence[this.pc]; 
    40                                 this.dispatch(insn); 
    41                         } 
    42                 } catch(e) { 
    43                         if(!(e instanceof HSPException)) { 
    44                                 throw e; 
    45                         } 
    46                         this.disposeException(e); 
    47                 } 
    48         }, 
    49         resume: function resume(callback) { 
    50                 try { 
    51                         if(callback) callback(); 
    52                         this.pc ++; 
    53                         while(true) { 
    54                                 var insn = this.sequence[this.pc]; 
    55                                 this.dispatch(insn); 
    56                         } 
    57                 } catch(e) { 
    58                         if(!(e instanceof HSPException)) { 
    59                                 throw e; 
    60                         } 
    61                         this.disposeException(e); 
    62                 } 
    63         }, 
    64         dispatch: function dispatch(insn) { 
    65                 var lhs, rhs; 
    66                 switch(insn.code) { 
    67                 case Instruction.Code.NOP: 
    68                         break; 
    69                 case Instruction.Code.PUSH: 
    70                         this.stack.push(insn.opts[0]); 
    71                         break; 
    72                 case Instruction.Code.PUSH_VAR: 
    73                         var varId = insn.opts[0]; 
    74                         var argc = insn.opts[1]; 
    75                         var indices = this.popIndices(argc); 
    76                         this.stack.push(new VariableAgent(this.variables[varId], indices)); 
    77                         break; 
    78                 case Instruction.Code.POP: 
    79                         this.stack.pop(); 
    80                         break; 
    81                 case Instruction.Code.DUP: 
    82                         this.stack.push(this.stack[this.stack.length-1]); 
    83                         break; 
    84                 case Instruction.Code.ADD: 
    85                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    86                         this.stack.push(lhs.add(rhs)); 
    87                         break; 
    88                 case Instruction.Code.SUB: 
    89                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    90                         this.stack.push(lhs.sub(rhs)); 
    91                         break; 
    92                 case Instruction.Code.MUL: 
    93                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    94                         this.stack.push(lhs.mul(rhs)); 
    95                         break; 
    96                 case Instruction.Code.DIV: 
    97                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    98                         this.stack.push(lhs.div(rhs)); 
    99                         break; 
    100                 case Instruction.Code.MOD: 
    101                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    102                         this.stack.push(lhs.mod(rhs)); 
    103                         break; 
    104                 case Instruction.Code.AND: 
    105                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    106                         this.stack.push(lhs.and(rhs)); 
    107                         break; 
    108                 case Instruction.Code.OR: 
    109                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    110                         this.stack.push(lhs.or(rhs)); 
    111                         break; 
    112                 case Instruction.Code.XOR: 
    113                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    114                         this.stack.push(lhs.xor(rhs)); 
    115                         break; 
    116                 case Instruction.Code.EQ: 
    117                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    118                         this.stack.push(lhs.eq(rhs)); 
    119                         break; 
    120                 case Instruction.Code.NE: 
    121                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    122                         this.stack.push(lhs.ne(rhs)); 
    123                         break; 
    124                 case Instruction.Code.GT: 
    125                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    126                         this.stack.push(lhs.gt(rhs)); 
    127                         break; 
    128                 case Instruction.Code.LT: 
    129                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    130                         this.stack.push(lhs.lt(rhs)); 
    131                         break; 
    132                 case Instruction.Code.GTEQ: 
    133                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    134                         this.stack.push(lhs.gteq(rhs)); 
    135                         break; 
    136                 case Instruction.Code.LTEQ: 
    137                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    138                         this.stack.push(lhs.lteq(rhs)); 
    139                         break; 
    140                 case Instruction.Code.RSH: 
    141                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    142                         this.stack.push(lhs.rsh(rhs)); 
    143                         break; 
    144                 case Instruction.Code.LSH: 
    145                         rhs = this.stack.pop(), lhs = this.stack.pop(); 
    146                         this.stack.push(lhs.lsh(rhs)); 
    147                         break; 
    148                 case Instruction.Code.GOTO: 
    149                         this.pc = insn.opts[0].pos; 
    150                         return; 
    151                 case Instruction.Code.IFNE: 
    152                         if(this.stack.pop().toIntValue()._value) { 
    153                                 this.pc = insn.opts[0].pos; 
    154                                 return; 
    155                         } 
    156                         break; 
    157                 case Instruction.Code.IFEQ: 
    158                         if(!this.stack.pop().toIntValue()._value) { 
    159                                 this.pc = insn.opts[0].pos; 
    160                                 return; 
    161                         } 
    162                         break; 
    163                 case Instruction.Code.SETVAR: 
    164                         var argc = insn.opts[0]; 
    165                         var args = Utils.aryPopN(this.stack, argc); 
    166                         var agent = this.stack.pop(); 
    167                         var variable = agent.variable; 
    168                         var indices = agent.indices.slice(); 
    169                         variable.assign(indices, args[0]); 
    170                         if(indices.length == 0) indices[0] = 0; 
    171                         indices[0] ++; 
    172                         for(var i = 1; i < argc; i ++) { 
    173                                 variable.assign(indices, args[i]); 
    174                                 indices[0] ++; 
    175                         } 
    176                         break; 
    177                 case Instruction.Code.EXPANDARRAY: 
    178                         var agent = this.stack[this.stack.length - 1]; 
    179                         agent.variable.expand(agent.indices); 
    180                         break; 
    181                 case Instruction.Code.INC: 
    182                         var agent = this.stack.pop(); 
    183                         agent.variable.expand(agent.indices); 
    184                         agent.assign(agent.add(new IntValue(1))); 
    185                         break; 
    186                 case Instruction.Code.DEC: 
    187                         var agent = this.stack.pop(); 
    188                         agent.variable.expand(agent.indices); 
    189                         agent.assign(agent.sub(new IntValue(1))); 
    190                         break; 
    191                 case Instruction.Code.CALL_BUILTIN_CMD: 
    192                         this.callBuiltinFunc(insn); 
    193                         break; 
    194                 case Instruction.Code.CALL_BUILTIN_FUNC: 
    195                         this.stack.push(this.callBuiltinFunc(insn)); 
    196                         break; 
    197                 case Instruction.Code.CALL_USERDEF_CMD: 
    198                 case Instruction.Code.CALL_USERDEF_FUNC: 
    199                         var userDefFunc = insn.opts[0]; 
    200                         var argc = insn.opts[1]; 
    201                         var args = Utils.aryPopN(this.stack, argc); 
    202                         this.callUserDefFunc(userDefFunc, args); 
    203                         break; 
    204                 case Instruction.Code.GETARG: 
    205                         var argNum = insn.opts[0]; 
    206                         this.stack.push(this.getArg(argNum)); 
    207                         break; 
    208                 case Instruction.Code.PUSH_ARG_VAR: 
    209                         var argNum = insn.opts[0]; 
    210                         var argc = insn.opts[1]; 
    211                         var variable = this.getArg(argNum); 
    212                         var indices = this.popIndices(argc); 
    213                         this.stack.push(new VariableAgent(variable, indices)); 
    214                         break; 
    215                 case Instruction.Code.PUSH_MEMBER: 
    216                         var memberNum = insn.opts[0]; 
    217                         var argc = insn.opts[1]; 
    218                         var struct = this.getThismod().toValue(); 
    219                         var indices = this.popIndices(argc); 
    220                         this.stack.push(new VariableAgent(struct.members[memberNum], indices)); 
    221                         break; 
    222                 case Instruction.Code.THISMOD: 
    223                         this.stack.push(this.getThismod()); 
    224                         break; 
    225                 case Instruction.Code.NEWMOD: 
    226                         var module = insn.opts[0]; 
    227                         var argc = insn.opts[1]; 
    228                         var args = Utils.aryPopN(this.stack, argc); 
    229                         var agent = args[0]; 
    230                         this.scanArg(agent, 'a', false); 
    231                         if(agent.getType() != VarType.STRUCT) { 
    232                                 agent.variable.dim(VarType.STRUCT, 1, 0, 0, 0); 
    233                         } 
    234                         var array = agent.variable.value; 
    235                         var offset = array.newmod(module); 
    236                         if(module.constructor) { 
    237                                 args[0] = new VariableAgent(agent.variable, [offset]); 
    238                                 this.callUserDefFunc(module.constructor, args); 
    239                         } else if(args.length > 1) { 
    240                                 throw new HSPError(ErrorCode.TOO_MANY_PARAMETERS); 
    241                         } 
    242                         break; 
    243                 case Instruction.Code.RETURN: 
    244                         var val = insn.opts[0] ? this.stack.pop() : undefined; 
    245                         if(this.frameStack.length == 0) { 
    246                                 throw new HSPError(ErrorCode.RETURN_WITHOUT_GOSUB); 
    247                         } 
    248                         var frame = this.frameStack.pop(); 
    249                         if(frame.userDefFunc && frame.userDefFunc.isCType) { 
    250                                 if(!val) throw new HSPError(ErrorCode.NORETVAL); 
    251                                 this.stack.push(val.toValue()); 
    252                         } else if(val) { 
    253                                 switch(val.getType()) { 
    254                                 case VarType.STR: 
    255                                         this.refstr.assign(0, val.toStrValue()); 
    256                                         break; 
    257                                 case VarType.DOUBLE: 
    258                                         this.refdval.assign(0, val.toDoubleValue()); 
    259                                         break; 
    260                                 case VarType.INT: 
    261                                         this.stat.assign(0, val.toIntValue()); 
    262                                         break; 
    263                                 default: 
    264                                         throw new HSPError(ErrorCode.TYPE_MISMATCH); 
    265                                 } 
    266                         } 
    267                         this.pc = frame.pc - 1; 
    268                         var runCallback = function() { 
    269                                 if(frame.callback) { 
    270                                         var fn = frame.callback(); 
    271                                         while(fn) { 
    272                                                 fn = fn(); 
     65        createMainLoop: function createMainLoop(literals, userDefFuncs) { 
     66                function push(line) { 
     67                        lines.push(Utils.strTimes('\t', indent) + line); 
     68                } 
     69                function pushJumpSubroutineCode(posExpr) { 
     70                        push('if(self.frameStack.length >= 256) {'); 
     71                        push('  throw new HSPError(ErrorCode.STACK_OVERFLOW);'); 
     72                        push('}'); 
     73                        push('self.frameStack.push(new Frame(self.pc + 1, null, null));'); 
     74                        push('self.pc = '+posExpr+';'); 
     75                } 
     76                var lines = []; 
     77                var indent = 0; 
     78                var sequence = this.sequence; 
     79                var operateMethodNames = 'add,sub,mul,div,mod,and,or,xor,eq,ne,gt,lt,gteq,lteq,rsh,lsh'.split(','); 
     80                 
     81                push('for(;;) {'); indent ++; 
     82                push('switch(self.pc) {'); 
     83                for(var pc = 0; pc < sequence.length; pc ++) { 
     84                        var insn = sequence[pc]; 
     85                        push('case '+pc+':'); indent ++; 
     86                        switch(insn.code) { 
     87                        case Instruction.Code.NOP: 
     88                                break; 
     89                        case Instruction.Code.PUSH: 
     90                                literals.push(insn.opts[0]); 
     91                                push('stack.push(literals['+(literals.length - 1)+']);'); 
     92                                break; 
     93                        case Instruction.Code.PUSH_VAR: 
     94                                var varId = insn.opts[0]; 
     95                                var argc = insn.opts[1]; 
     96                                push('stack.push(new VariableAgent(variables['+varId+'], self.popIndices('+argc+')));'); 
     97                                break; 
     98                        case Instruction.Code.POP: 
     99                                push('stack.pop();'); 
     100                                break; 
     101                        case Instruction.Code.DUP: 
     102                                push('stack.push(stack[stack.length-1]);'); 
     103                                break; 
     104                        case Instruction.Code.ADD: 
     105                        case Instruction.Code.SUB: 
     106                        case Instruction.Code.MUL: 
     107                        case Instruction.Code.DIV: 
     108                        case Instruction.Code.MOD: 
     109                        case Instruction.Code.AND: 
     110                        case Instruction.Code.OR: 
     111                        case Instruction.Code.XOR: 
     112                        case Instruction.Code.EQ: 
     113                        case Instruction.Code.NE: 
     114                        case Instruction.Code.GT: 
     115                        case Instruction.Code.LT: 
     116                        case Instruction.Code.GTEQ: 
     117                        case Instruction.Code.LTEQ: 
     118                        case Instruction.Code.RSH: 
     119                        case Instruction.Code.LSH: 
     120                                push('var rhs = stack.pop();'); 
     121                                push('stack[stack.length - 1] = stack[stack.length - 1].'+ 
     122                                         operateMethodNames[insn.code - Instruction.Code.ADD]+'(rhs);'); 
     123                                break; 
     124                        case Instruction.Code.GOTO: 
     125                                push('self.pc = '+insn.opts[0].pos+';'); 
     126                                push('continue;'); 
     127                                break; 
     128                        case Instruction.Code.IFNE: 
     129                                push('if(stack.pop().toIntValue()._value) {'); 
     130                                push('    self.pc = '+insn.opts[0].pos+';'); 
     131                                push('    continue;'); 
     132                                push('}'); 
     133                                break; 
     134                        case Instruction.Code.IFEQ: 
     135                                push('if(!stack.pop().toIntValue()._value) {'); 
     136                                push('    self.pc = '+insn.opts[0].pos+';'); 
     137                                push('    continue;'); 
     138                                push('}'); 
     139                                break; 
     140                        case Instruction.Code.SETVAR: 
     141                                var argc = insn.opts[0]; 
     142                                if(argc > 1) { 
     143                                        push('var args = Utils.aryPopN(stack, '+argc+');'); 
     144                                        push('var agent = stack.pop();'); 
     145                                        push('var variable = agent.variable;'); 
     146                                        push('var indices = agent.indices.slice();'); 
     147                                        push('if(indices.length == 0) indices[0] = 0;'); 
     148                                        for(var i = 0; i < argc; i ++) { 
     149                                                push('variable.assign(indices, args['+i+']);'); 
     150                                                push('indices[0] ++;'); 
    273151                                        } 
    274                                 } 
    275                         }; 
    276                         if(frame.userDefFunc) { 
    277                                 this.deleteLocalVars(frame.userDefFunc.paramTypes, frame.args, runCallback); 
    278                         } else { 
    279                                 runCallback(); 
    280                         } 
    281                         break; 
    282                 case Instruction.Code.DELMOD: 
    283                         var v = this.stack.pop(); 
    284                         this.scanArg(v, 'v', false); 
    285                         if(v.getType() != VarType.STRUCT) { 
    286                                 throw new HSPError(ErrorCode.TYPE_MISMATCH); 
    287                         } 
    288                         this.deleteStruct(v); 
    289                         break; 
    290                 case Instruction.Code.REPEAT: 
    291                         if(this.loopStack.length >= 31) { 
    292                                 throw new HSPError(ErrorCode.TOO_MANY_NEST); 
    293                         } 
    294                         var label = insn.opts[0]; 
    295                         var argc = insn.opts[1]; 
    296                         var begin = 0, end = Infinity; 
    297                         if(argc == 2) { 
    298                                 var begin = this.stack.pop(); 
    299                                 this.scanArg(begin, 'n', false); 
    300                                 begin = begin.toIntValue()._value; 
    301                         } 
    302                         if(argc >= 1) { 
    303                                 var end = this.stack.pop(); 
    304                                 this.scanArg(end, 'n', false); 
    305                                 end = end.toIntValue()._value; 
    306                                 if(end < 0) end = Infinity; 
    307                         } 
    308                         if(end == 0) { 
    309                                 this.pc = label.pos - 1; 
    310                                 break; 
    311                         } 
    312                         end += begin; 
    313                         this.loopStack.push(new LoopData(begin, end, this.pc + 1)); 
    314                         break; 
    315                 case Instruction.Code.LOOP: 
    316                         if(this.loopStack.length == 0) { 
    317                                 throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT); 
    318                         } 
    319                         var data = this.loopStack[this.loopStack.length - 1]; 
    320                         data.cnt ++; 
    321                         if(data.cnt >= data.end) { 
    322                                 this.loopStack.pop(); 
    323                                 break; 
    324                         } 
    325                         this.pc = data.pc - 1; 
    326                         break; 
    327                 case Instruction.Code.CNT: 
    328                         if(this.loopStack.length == 0) { 
    329                                 this.stack.push(new IntValue(0)); 
    330                                 break; 
    331                         } 
    332                         this.stack.push(new IntValue(this.loopStack[this.loopStack.length - 1].cnt)); 
    333                         break; 
    334                 case Instruction.Code.CONTINUE: 
    335                         if(this.loopStack.length == 0) { 
    336                                 throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT); 
    337                         } 
    338                         var data = this.loopStack[this.loopStack.length - 1]; 
    339                         var label = insn.opts[0]; 
    340                         var argc = insn.opts[1]; 
    341                         var newCnt = data.cnt + 1; 
    342                         if(argc) { 
    343                                 newCnt = this.stack.pop(); 
    344                                 this.scanArg(newCnt, 'n', false); 
    345                                 newCnt = newCnt.toIntValue()._value; 
    346                         } 
    347                         data.cnt = newCnt; 
    348                         if(data.cnt >= data.end) { 
    349                                 this.loopStack.pop(); 
    350                                 this.pc = label.pos - 1; 
    351                                 break; 
    352                         } 
    353                         this.pc = data.pc - 1; 
    354                         break; 
    355                 case Instruction.Code.BREAK: 
    356                         if(this.loopStack.length == 0) { 
    357                                 throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT); 
    358                         } 
    359                         var label = insn.opts[0]; 
    360                         this.loopStack.pop(); 
    361                         this.pc = label.pos - 1; 
    362                         break; 
    363                 case Instruction.Code.FOREACH: 
    364                         if(this.loopStack.length >= 31) { 
    365                                 throw new HSPError(ErrorCode.TOO_MANY_NEST); 
    366                         } 
    367                         this.loopStack.push(new LoopData(0, Infinity, this.pc + 1)); 
    368                         break; 
    369                 case Instruction.Code.EACHCHK: 
    370                         if(this.loopStack.length == 0) { 
    371                                 throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT); 
    372                         } 
    373                         var label = insn.opts[0]; 
    374                         var v = this.stack.pop(); 
    375                         this.scanArg(v, 'v', false); 
    376                         var data = this.loopStack[this.loopStack.length - 1]; 
    377                         if(data.cnt >= v.variable.getL0()) { 
    378                                 this.loopStack.pop(); 
    379                                 this.pc = label.pos - 1; 
    380                                 break; 
    381                         } 
    382                         if(v.variable.at([data.cnt]).isUsing() == false) { // label 型 や struct 型の empty を飛ばす 
    383                                 data.cnt ++; 
    384                                 if(data.cnt >= data.end) { 
    385                                         this.loopStack.pop(); 
    386                                         this.pc = label.pos - 1; 
    387                                         break; 
    388                                 } 
    389                                 this.pc = data.pc - 1; 
    390                         } 
    391                         break; 
    392                 case Instruction.Code.GOSUB: 
    393                         this.subroutineJump(insn.opts[0].pos); 
    394                         break; 
    395                 case Instruction.Code.GOTO_EXPR: 
    396                         this.pc = this.scanArg(this.stack.pop(), 'l').toValue().pos - 1; 
    397                         break; 
    398                 case Instruction.Code.GOSUB_EXPR: 
    399                         this.subroutineJump(this.scanArg(this.stack.pop(), 'l').toValue().pos); 
    400                         break; 
    401                 case Instruction.Code.EXGOTO: 
    402                         var pos = this.scanArg(this.stack.pop(), 'l').toValue().pos; 
    403                         var b = this.scanArg(this.stack.pop(), 'n').toIntValue()._value; 
    404                         var mode = this.scanArg(this.stack.pop(), 'n').toIntValue()._value; 
    405                         var a = this.scanArg(this.scanArg(this.stack.pop(), 'v'), 'i').toIntValue()._value; 
    406                         if(mode >= 0) { 
    407                                 if(a >= b) this.pc = pos - 1; 
    408                         } else { 
    409                                 if(a <= b) this.pc = pos - 1; 
    410                         } 
    411                         break; 
    412                 case Instruction.Code.EXGOTO_OPT1: 
    413                         var a = this.scanArg(this.variables[insn.opts[0]].at(0), 'i').toIntValue()._value; 
    414                         var pos = insn.opts[1].pos; 
    415                         var b = this.scanArg(this.stack.pop(), 'n').toIntValue()._value; 
    416                         var mode = this.scanArg(this.stack.pop(), 'n').toIntValue()._value; 
    417                         if(mode >= 0) { 
    418                                 if(a >= b) this.pc = pos - 1; 
    419                         } else { 
    420                                 if(a <= b) this.pc = pos - 1; 
    421                         } 
    422                         break; 
    423                 case Instruction.Code.EXGOTO_OPT2: 
    424                         var a = this.scanArg(this.variables[insn.opts[0]].at(0), 'i').toIntValue()._value; 
    425                         var pos = insn.opts[1].pos; 
    426                         var b = this.scanArg(this.stack.pop(), 'n').toIntValue()._value; 
    427                         if(a >= b) this.pc = pos - 1; 
    428                         break; 
    429                 case Instruction.Code.EXGOTO_OPT3: 
    430                         var a = this.scanArg(this.variables[insn.opts[0]].at(0), 'i').toIntValue()._value; 
    431                         var pos = insn.opts[1].pos; 
    432                         var b = this.scanArg(this.stack.pop(), 'n').toIntValue()._value; 
    433                         if(a <= b) this.pc = pos - 1; 
    434                         break; 
    435                 case Instruction.Code.ON: 
    436                         var argc = insn.opts[0]; 
    437                         var isGosub = insn.opts[1]; 
    438                         for(var i = this.stack.length - argc, l = this.stack.length; i < l; i ++) { 
    439                                 this.scanArg(this.stack[i], 'l'); 
    440                         } 
    441                         var n = this.scanArg(this.stack[this.stack.length - argc - 1], 'n').toIntValue()._value; 
    442                         if(!(0 <= n && n < argc)) break; 
    443                         var pos = this.stack[this.stack.length - argc + n].toValue().pos; 
    444                         this.stack.length -= argc + 1; 
    445                         if(isGosub) { 
    446                                 this.subroutineJump(pos); 
    447                         } else { 
    448                                 this.pc = pos - 1; 
    449                         } 
    450                         break; 
    451                 default: 
    452                         throw new Error("未対応の命令コード: "+insn.code); 
    453                 } 
    454                 this.pc ++; 
     152                                } else { 
     153                                        push('var arg = stack.pop();'); 
     154                                        push('var agent = stack.pop();'); 
     155                                        push('agent.variable.assign(agent.indices, arg);'); 
     156                                } 
     157                                break; 
     158                        case Instruction.Code.EXPANDARRAY: 
     159                                push('var agent = stack[stack.length - 1];'); 
     160                                push('agent.variable.expand(agent.indices);'); 
     161                                break; 
     162                        case Instruction.Code.INC: 
     163                                push('var agent = stack.pop();'); 
     164                                push('agent.variable.expand(agent.indices);'); 
     165                                push('agent.assign(agent.add(new IntValue(1)));'); 
     166                                break; 
     167                        case Instruction.Code.DEC: 
     168                                push('var agent = stack.pop();'); 
     169                                push('agent.variable.expand(agent.indices);'); 
     170                                push('agent.assign(agent.sub(new IntValue(1)));'); 
     171                                break; 
     172                        case Instruction.Code.CALL_BUILTIN_CMD: 
     173                        case Instruction.Code.CALL_BUILTIN_FUNC: 
     174                                var type = insn.opts[0]; 
     175                                var subid = insn.opts[1]; 
     176                                var argc = insn.opts[2]; 
     177                                push('var func = BuiltinFuncs['+type+']['+subid+'];'); 
     178                                push('if(!func) throw new HSPError(ErrorCode.UNSUPPORTED_FUNCTION);'); 
     179                                push('var args = Utils.aryPopN(stack, '+argc+');'); 
     180                                if(insn.code == Instruction.Code.CALL_BUILTIN_FUNC) { 
     181                                        push('stack.push(func.apply(self, args));'); 
     182                                } else { 
     183                                        push('func.apply(self, args);'); 
     184                                } 
     185                                break; 
     186                        case Instruction.Code.CALL_USERDEF_CMD: 
     187                        case Instruction.Code.CALL_USERDEF_FUNC: 
     188                                var userDefFunc = insn.opts[0]; 
     189                                var argc = insn.opts[1]; 
     190                                if(!userDefFuncs[userDefFunc.id]) { 
     191                                        userDefFuncs[userDefFunc.id] = userDefFunc; 
     192                                } 
     193                                push('self.callUserDefFunc(userDefFuncs['+userDefFunc.id+'], '+ 
     194                                         'Utils.aryPopN(stack, '+argc+'));'); 
     195                                push('self.pc ++;'); 
     196                                push('continue;'); 
     197                                break; 
     198                        case Instruction.Code.GETARG: 
     199                                var argNum = insn.opts[0]; 
     200                                push('stack.push(self.getArg('+argNum+'));'); 
     201                                break; 
     202                        case Instruction.Code.PUSH_ARG_VAR: 
     203                                var argNum = insn.opts[0]; 
     204                                var argc = insn.opts[1]; 
     205                                push('var variable = self.getArg('+argNum+');'); 
     206                                push('var indices = self.popIndices('+argc+');'); 
     207                                push('stack.push(new VariableAgent(variable, indices));'); 
     208                                break; 
     209                        case Instruction.Code.PUSH_MEMBER: 
     210                                var memberNum = insn.opts[0]; 
     211                                var argc = insn.opts[1]; 
     212                                push('var struct = self.getThismod().toValue();'); 
     213                                push('var indices = self.popIndices('+argc+');'); 
     214                                push('stack.push(new VariableAgent(struct.members['+memberNum+'], indices));'); 
     215                                break; 
     216                        case Instruction.Code.THISMOD: 
     217                                push('stack.push(self.getThismod());'); 
     218                                break; 
     219                        case Instruction.Code.NEWMOD: 
     220                                var module = insn.opts[0]; 
     221                                var argc = insn.opts[1]; 
     222                                if(!userDefFuncs[module.id]) { 
     223                                        userDefFuncs[module.id] = module; 
     224                                } 
     225                                var moduleExpr = 'userDefFuncs['+module.id+']'; 
     226                                push('var args = Utils.aryPopN(stack, '+argc+');'); 
     227                                push('var agent = self.scanArg(args[0], "a");'); 
     228                                push('if(agent.getType() != '+VarType.STRUCT+') {'); 
     229                                push('    agent.variable.dim('+VarType.STRUCT+', 1, 0, 0, 0);'); 
     230                                push('}'); 
     231                                push('var array = agent.variable.value;'); 
     232                                push('var offset = array.newmod('+moduleExpr+');'); 
     233                                if(module.constructor) { 
     234                                        push('args[0] = new VariableAgent(agent.variable, [offset]);'); 
     235                                        if(!userDefFuncs[module.constructor.id]) { 
     236                                                userDefFuncs[module.constructor.id] = module.constructor; 
     237                                        } 
     238                                        push('self.callUserDefFunc(userDefFuncs['+module.constructor.id+'], args);'); 
     239                                        push('self.pc ++;'); 
     240                                        push('continue;'); 
     241                                } else if(argc > 1) { 
     242                                        push('throw new HSPError(ErrorCode.TOO_MANY_PARAMETERS);') 
     243                                } 
     244                                break; 
     245                        case Instruction.Code.RETURN: 
     246                                if(insn.opts[0]) { 
     247                                        push('self.return_(stack.pop());'); 
     248                                } else { 
     249                                        push('self.return_();'); 
     250                                } 
     251                                push('self.pc ++;'); 
     252                                push('continue;'); 
     253                                break; 
     254                        case Instruction.Code.DELMOD: 
     255                                push('var v = self.scanArg(stack.pop(), "v");'); 
     256                                push('if(v.getType() != VarType.STRUCT) {'); 
     257                                push('    throw new HSPError(ErrorCode.TYPE_MISMATCH);'); 
     258                                push('}'); 
     259                                push('self.deleteStruct(v);'); 
     260                                push('self.pc ++;'); 
     261                                push('continue;'); 
     262                                break; 
     263                        case Instruction.Code.REPEAT: 
     264                                var pos = insn.opts[0].pos; 
     265                                var argc = insn.opts[1]; 
     266                                push('if(self.loopStack.length >= 31) {'); 
     267                                push('    throw new HSPError(ErrorCode.TOO_MANY_NEST);'); 
     268                                push('}'); 
     269                                if(argc == 2) { 
     270                                        push('var begin = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     271                                } else { 
     272                                        push('var begin = 0;'); 
     273                                } 
     274                                if(argc >= 1) { 
     275                                        push('var end = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     276                                        push('if(end < 0) end = Infinity;'); 
     277                                } else { 
     278                                        push('var end = Infinity;'); 
     279                                } 
     280                                push('if(end == 0) {'); 
     281                                push('    self.pc = '+pos+';'); 
     282                                push('    continue;'); 
     283                                push('}'); 
     284                                push('end += begin;'); 
     285                                push('self.loopStack.push(new LoopData(begin, end, '+(pc + 1)+'));'); 
     286                                break; 
     287                        case Instruction.Code.LOOP: 
     288                                push('if(self.loopStack.length == 0) {'); 
     289                                push('    throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT);'); 
     290                                push('}'); 
     291                                push('var data = self.loopStack[self.loopStack.length - 1];'); 
     292                                push('data.cnt ++;'); 
     293                                push('if(data.cnt < data.end) {'); 
     294                                push('    self.pc = data.pc;'); 
     295                                push('    continue;'); 
     296                                push('}'); 
     297                                push('self.loopStack.pop();'); 
     298                                break; 
     299                        case Instruction.Code.CNT: 
     300                                push('if(self.loopStack.length == 0) {'); 
     301                                push('    stack.push(new IntValue(0));'); 
     302                                push('} else {'); 
     303                                push('    stack.push(new IntValue(self.loopStack[self.loopStack.length - 1].cnt));'); 
     304                                push('}'); 
     305                                break; 
     306                        case Instruction.Code.CONTINUE: 
     307                                var pos = insn.opts[0].pos; 
     308                                var argc = insn.opts[1]; 
     309                                push('if(self.loopStack.length == 0) {'); 
     310                                push('    throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT);'); 
     311                                push('}'); 
     312                                push('var data = self.loopStack[self.loopStack.length - 1];'); 
     313                                var newCntExpr; 
     314                                if(argc) { 
     315                                        newCntExpr = '(data.cnt = self.scanArg(self.stack.pop(), "n").toIntValue()._value)'; 
     316                                } else { 
     317                                        newCntExpr = '++data.cnt'; 
     318                                } 
     319                                push('if('+newCntExpr+' >= data.end) {'); 
     320                                push('    self.loopStack.pop();'); 
     321                                push('    self.pc = '+pos+';'); 
     322                                push('} else {'); 
     323                                push('    self.pc = data.pc;'); 
     324                                push('}'); 
     325                                push('continue;'); 
     326                                break; 
     327                        case Instruction.Code.BREAK: 
     328                                var label = insn.opts[0]; 
     329                                push('if(self.loopStack.length == 0) {'); 
     330                                push('    throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT);'); 
     331                                push('}'); 
     332                                push('self.loopStack.pop();'); 
     333                                push('self.pc = '+label.pos+';'); 
     334                                push('continue;'); 
     335                                break; 
     336                        case Instruction.Code.FOREACH: 
     337                                push('if(self.loopStack.length >= 31) {'); 
     338                                push('    throw new HSPError(ErrorCode.TOO_MANY_NEST);'); 
     339                                push('}'); 
     340                                push('self.loopStack.push(new LoopData(0, Infinity, '+(pc + 1)+'));'); 
     341                                break; 
     342                        case Instruction.Code.EACHCHK: 
     343                                push('if(self.loopStack.length == 0) {'); 
     344                                push('    throw new HSPError(ErrorCode.LOOP_WITHOUT_REPEAT);') 
     345                                push('}') 
     346                                var pos = insn.opts[0].pos; 
     347                                push('var v = self.scanArg(stack.pop(), "v");'); 
     348                                push('var data = self.loopStack[self.loopStack.length - 1];'); 
     349                                push('if(data.cnt >= v.variable.getL0()) {') 
     350                                push('    self.loopStack.pop();'); 
     351                                push('    self.pc = '+pos+';'); 
     352                                push('    continue;'); 
     353                                push('}'); 
     354                                push('if(v.variable.at([data.cnt]).isUsing() == false) {'); // label 型 や struct 型の empty を飛ばす 
     355                                push('    data.cnt ++;'); 
     356                                push('    if(data.cnt >= data.end) {'); 
     357                                push('        self.loopStack.pop();'); 
     358                                push('        self.pc = '+pos+';'); 
     359                                push('    } else {'); 
     360                                push('        self.pc = data.pc - 1;'); 
     361                                push('    }'); 
     362                                push('    continue;'); 
     363                                push('}'); 
     364                                break; 
     365                        case Instruction.Code.GOSUB: 
     366                                pushJumpSubroutineCode(insn.opts[0].pos); 
     367                                push('continue;'); 
     368                                break; 
     369                        case Instruction.Code.GOTO_EXPR: 
     370                                push('self.pc = self.scanArg(stack.pop(), "l").toValue().pos;'); 
     371                                push('continue;'); 
     372                                break; 
     373                        case Instruction.Code.GOSUB_EXPR: 
     374                                pushJumpSubroutineCode('self.scanArg(stack.pop(), "l").toValue().pos'); 
     375                                push('continue;'); 
     376                                break; 
     377                        case Instruction.Code.EXGOTO: 
     378                                push('var pos = self.scanArg(stack.pop(), "l").toValue().pos;'); 
     379                                push('var b = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     380                                push('var mode = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     381                                push('var a = self.scanArg(self.scanArg(stack.pop(), "v"), "i").toIntValue()._value;'); 
     382                                push('if(mode >= 0) {'); 
     383                                push('  if(a >= b) { self.pc = pos; continue; }'); 
     384                                push('} else {'); 
     385                                push('  if(a <= b) { self.pc = pos; continue; }'); 
     386                                push('}'); 
     387                                break; 
     388                        case Instruction.Code.EXGOTO_OPT1: 
     389                                var pos = insn.opts[1].pos; 
     390                                push('var a = self.scanArg(variables['+insn.opts[0]+'].at(0), "i").toIntValue()._value;'); 
     391                                push('var b = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     392                                push('var mode = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     393                                push('if(mode >= 0) {'); 
     394                                push('  if(a >= b) { self.pc = '+pos+'; continue; }'); 
     395                                push('} else {'); 
     396                                push('  if(a <= b) { self.pc = '+pos+'; continue; }'); 
     397                                push('}'); 
     398                                break; 
     399                        case Instruction.Code.EXGOTO_OPT2: 
     400                                var pos = insn.opts[1].pos; 
     401                                push('var a = self.scanArg(variables['+insn.opts[0]+'].at(0), "i").toIntValue()._value;'); 
     402                                push('var b = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     403                                push('if(a >= b) { self.pc = '+pos+'; continue; }'); 
     404                                break; 
     405                        case Instruction.Code.EXGOTO_OPT3: 
     406                                var pos = insn.opts[1].pos; 
     407                                push('var a = self.scanArg(variables['+insn.opts[0]+'].at(0), "i").toIntValue()._value;'); 
     408                                push('var b = self.scanArg(stack.pop(), "n").toIntValue()._value;'); 
     409                                push('if(a <= b) { self.pc = '+pos+'; continue; }'); 
     410                                break; 
     411                        case Instruction.Code.ON: 
     412                                var argc = insn.opts[0]; 
     413                                var isGosub = insn.opts[1]; 
     414                                push('var len = stack.length;'); 
     415                                for(var i = 0; i < argc; i ++) { 
     416                                        push('self.scanArg(stack[len - '+(argc - i)+'], "l");'); 
     417                                } 
     418                                push('var n = self.scanArg(stack[len - '+(argc + 1)+'], "n").toIntValue()._value;'); 
     419                                push('if(!(0 <= n && n < argc)) break;'); 
     420                                push('var pos = stack[len - '+argc+' + n].toValue().pos;'); 
     421                                push('stack.length -= '+(argc + 1)+';'); 
     422                                if(isGosub) { 
     423                                        pushJumpSubroutineCode('pos'); 
     424                                        push('continue;'); 
     425                                } else { 
     426                                        push('self.pc = pos;'); 
     427                                        push('continue;'); 
     428                                } 
     429                                break; 
     430                        default: 
     431                                throw new Error("未対応の命令コード: "+insn.code); 
     432                        } 
     433                        push('self.pc ++;'); 
     434                        indent --; 
     435                } 
     436                push('}'); 
     437                indent --; push('}'); 
     438                //print(lines.join("\n")); 
     439                return lines.join("\n"); 
    455440        }, 
    456441        callBuiltinFunc: function callBuiltinFunc(insn) { 
     
    525510                this.pc = userDefFunc.label.pos - 1; 
    526511        }, 
    527         subroutineJump: function subroutineJump(pos) { 
    528                 if(this.frameStack.length >= 256) { 
    529                         throw new HSPError(ErrorCode.STACK_OVERFLOW); 
    530                 } 
    531                 this.frameStack.push(new Frame(this.pc + 1, null, null)); 
    532                 this.pc = pos - 1; 
     512        return_: function return_(val) { 
     513                if(this.frameStack.length == 0) { 
     514                        throw new HSPError(ErrorCode.RETURN_WITHOUT_GOSUB); 
     515                } 
     516                var frame = this.frameStack.pop(); 
     517                if(frame.userDefFunc && frame.userDefFunc.isCType) { 
     518                        if(!val) throw new HSPError(ErrorCode.NORETVAL); 
     519                        this.stack.push(val.toValue()); 
     520                } else if(val) { 
     521                        switch(val.getType()) { 
     522                        case VarType.STR: 
     523                                this.refstr.assign(0, val.toStrValue()); 
     524                                break; 
     525                        case VarType.DOUBLE: 
     526                                this.refdval.assign(0, val.toDoubleValue()); 
     527                                break; 
     528                        case VarType.INT: 
     529                                this.stat.assign(0, val.toIntValue()); 
     530                                break; 
     531                        default: 
     532                                throw new HSPError(ErrorCode.TYPE_MISMATCH); 
     533                        } 
     534                } 
     535                this.pc = frame.pc - 1; 
     536                var runCallback = function() { 
     537                        if(frame.callback) { 
     538                                var fn = frame.callback(); 
     539                                while(fn) { 
     540                                        fn = fn(); 
     541                                } 
     542                        } 
     543                }; 
     544                if(frame.userDefFunc) { 
     545                        this.deleteLocalVars(frame.userDefFunc.paramTypes, frame.args, runCallback); 
     546                } else { 
     547                        runCallback(); 
     548                } 
    533549        }, 
    534550        popIndices: function popIndices(argc) { 
  • lang/javascript/hsp-on-js/trunk/src/user-def-func.js

    r21766 r22778  
    1 function UserDefFunc(isCType, name, label, paramTypes) { 
     1function UserDefFunc(isCType, name, label, paramTypes, id) { 
    22        this.isCType = isCType; 
    33        this.name = name; 
    44        this.label = label; 
    55        this.paramTypes = paramTypes; 
     6        this.id = id; 
    67} 
    78 
     
    1011}; 
    1112 
    12 function Module(name, constructor, destructor, membersCount) { 
     13function Module(name, constructor, destructor, membersCount, id) { 
    1314        this.name = name; 
    1415        this.constructor = constructor; 
    1516        this.destructor = destructor; 
    1617        this.membersCount = membersCount; 
     18        this.id = id; 
    1719} 
    1820