@@ -179,9 +179,10 @@ function compile(node: Node, cg: CodeGenerator): CompileResult {
179179const codeGenerators : { [ type : string ] : ( node : Node , cg : CodeGenerator ) => CompileResult } = {
180180 Block : ( node : Node , cg : CodeGenerator ) => {
181181 cg . symbolTable . extend ( )
182+ const block = node as Block
182183 let maxStack = 0
183- let resultType = ''
184- ; ( node as Block ) . blockStatements . forEach ( x => {
184+ let resultType = EMPTY_TYPE
185+ block . blockStatements . forEach ( x => {
185186 const { stackSize : stackSize , resultType : type } = compile ( x , cg )
186187 maxStack = Math . max ( maxStack , stackSize )
187188 resultType = type
@@ -418,8 +419,10 @@ const codeGenerators: { [type: string]: (node: Node, cg: CodeGenerator) => Compi
418419 literalType : { kind : kind , value : value }
419420 } = node
420421 const boolValue = value === 'true'
421- if ( kind === 'BooleanLiteral' && onTrue === boolValue ) {
422- cg . addBranchInstr ( OPCODE . GOTO , targetLabel )
422+ if ( kind === 'BooleanLiteral' ) {
423+ if ( onTrue === boolValue ) {
424+ cg . addBranchInstr ( OPCODE . GOTO , targetLabel )
425+ }
423426 return { stackSize : 0 , resultType : cg . symbolTable . generateFieldDescriptor ( 'boolean' ) }
424427 }
425428 }
@@ -470,20 +473,20 @@ const codeGenerators: { [type: string]: (node: Node, cg: CodeGenerator) => Compi
470473 } else if ( op in reverseLogicalOp ) {
471474 if ( isNullLiteral ( left ) ) {
472475 // still use l to represent the first argument pushed onto stack
473- l = f ( right , targetLabel , onTrue )
476+ l = compile ( right , cg )
474477 cg . addBranchInstr (
475478 onTrue !== ( op === '!=' ) ? OPCODE . IFNULL : OPCODE . IFNONNULL ,
476479 targetLabel
477480 )
478481 } else if ( isNullLiteral ( right ) ) {
479- l = f ( left , targetLabel , onTrue )
482+ l = compile ( left , cg )
480483 cg . addBranchInstr (
481484 onTrue !== ( op === '!=' ) ? OPCODE . IFNULL : OPCODE . IFNONNULL ,
482485 targetLabel
483486 )
484487 } else {
485- l = f ( left , targetLabel , onTrue )
486- r = f ( right , targetLabel , onTrue )
488+ l = compile ( left , cg )
489+ r = compile ( right , cg )
487490 cg . addBranchInstr ( onTrue ? logicalOp [ op ] : reverseLogicalOp [ op ] , targetLabel )
488491 }
489492 return {
@@ -496,7 +499,9 @@ const codeGenerators: { [type: string]: (node: Node, cg: CodeGenerator) => Compi
496499 }
497500 }
498501
499- return compile ( node , cg )
502+ const res = compile ( node , cg )
503+ cg . addBranchInstr ( onTrue ? OPCODE . IFNE : OPCODE . IFEQ , cg . labels [ cg . labels . length - 1 ] )
504+ return res
500505 }
501506 return f ( node , cg . labels [ cg . labels . length - 1 ] , false )
502507 } ,
@@ -544,8 +549,11 @@ const codeGenerators: { [type: string]: (node: Node, cg: CodeGenerator) => Compi
544549 } ,
545550
546551 ExpressionStatement : ( node : Node , cg : CodeGenerator ) => {
547- const n = node as ExpressionStatement
548- return compile ( n . stmtExp , cg )
552+ const { stmtExp } = node as ExpressionStatement
553+ if ( stmtExp . kind === 'PrefixExpression' || stmtExp . kind === 'PostfixExpression' ) {
554+ return codeGenerators [ 'IncrementDecrementExpression' ] ( stmtExp , cg )
555+ }
556+ return compile ( stmtExp , cg )
549557 } ,
550558
551559 MethodInvocation : ( node : Node , cg : CodeGenerator ) => {
@@ -703,6 +711,18 @@ const codeGenerators: { [type: string]: (node: Node, cg: CodeGenerator) => Compi
703711 }
704712 } ,
705713
714+ IncrementDecrementExpression : ( node : Node , cg : CodeGenerator ) => {
715+ // handle cases of ++x, x++, x--, --x that do not add object to operand stack
716+ if ( node . kind === 'PrefixExpression' || node . kind === 'PostfixExpression' ) {
717+ const { name } = node . expression as ExpressionName
718+ const info = cg . symbolTable . queryVariable ( name )
719+ if ( ! Array . isArray ( info ) ) {
720+ cg . code . push ( OPCODE . IINC , info . index , node . operator === '++' ? 1 : - 1 )
721+ }
722+ }
723+ return { stackSize : 0 , resultType : EMPTY_TYPE }
724+ } ,
725+
706726 PrefixExpression : ( node : Node , cg : CodeGenerator ) => {
707727 const { operator : op , expression : expr } = node as PrefixExpression
708728 if ( op === '++' || op === '--' ) {
@@ -799,9 +819,11 @@ const codeGenerators: { [type: string]: (node: Node, cg: CodeGenerator) => Compi
799819 field
800820 )
801821 }
822+ const fetchedFieldTypeDescriptor = ( fieldInfos [ fieldInfos . length - 1 ] as FieldInfo )
823+ . typeDescriptor
802824 return {
803- stackSize : 1 ,
804- resultType : ( fieldInfos [ fieldInfos . length - 1 ] as FieldInfo ) . typeDescriptor
825+ stackSize : 1 + ( [ 'D' , 'J' ] . includes ( fetchedFieldTypeDescriptor ) ? 1 : 0 ) ,
826+ resultType : fetchedFieldTypeDescriptor
805827 }
806828 } else {
807829 cg . code . push (
@@ -917,14 +939,19 @@ class CodeGenerator {
917939 }
918940
919941 methodNode . methodHeader . formalParameterList . forEach ( p => {
920- this . symbolTable . insertVariableInfo ( {
942+ const paramInfo = {
921943 name : p . identifier ,
922944 accessFlags : 0 ,
923945 index : this . maxLocals ,
924946 typeName : p . unannType ,
925947 typeDescriptor : this . symbolTable . generateFieldDescriptor ( p . unannType )
926- } )
927- this . maxLocals ++
948+ }
949+ this . symbolTable . insertVariableInfo ( paramInfo )
950+ if ( [ 'D' , 'J' ] . includes ( paramInfo . typeDescriptor ) ) {
951+ this . maxLocals += 2
952+ } else {
953+ this . maxLocals ++
954+ }
928955 } )
929956
930957 if ( methodNode . methodHeader . identifier === '<init>' ) {
0 commit comments