From d1d9a5d6e1f44b24972b3004e4ef2eb46e32daca Mon Sep 17 00:00:00 2001 From: mrab Date: Tue, 14 May 2024 12:29:55 +0200 Subject: [PATCH] constructor and method call using this --- src/ByteCode/ClassFile.hs | 111 ++++++++++++++-------------- src/ByteCode/ClassFile/Generator.hs | 18 +++-- src/Main.hs | 2 +- src/Typecheck.hs | 2 +- 4 files changed, 72 insertions(+), 61 deletions(-) diff --git a/src/ByteCode/ClassFile.hs b/src/ByteCode/ClassFile.hs index a27be11..7798cf8 100644 --- a/src/ByteCode/ClassFile.hs +++ b/src/ByteCode/ClassFile.hs @@ -42,6 +42,7 @@ data Operation = Opiadd | Opreturn | Opireturn | Opareturn + | Opinvokespecial Word16 | Opgoto Word16 | Opsipush Word16 | Opldc_w Word16 @@ -90,33 +91,34 @@ emptyClassFile = ClassFile { } opcodeEncodingLength :: Operation -> Word16 -opcodeEncodingLength Opiadd = 1 -opcodeEncodingLength Opisub = 1 -opcodeEncodingLength Opimul = 1 -opcodeEncodingLength Opidiv = 1 -opcodeEncodingLength Opiand = 1 -opcodeEncodingLength Opior = 1 -opcodeEncodingLength Opixor = 1 -opcodeEncodingLength Opineg = 1 -opcodeEncodingLength (Opif_icmplt _) = 3 -opcodeEncodingLength (Opif_icmple _) = 3 -opcodeEncodingLength (Opif_icmpgt _) = 3 -opcodeEncodingLength (Opif_icmpge _) = 3 -opcodeEncodingLength (Opif_icmpeq _) = 3 -opcodeEncodingLength (Opif_icmpne _) = 3 -opcodeEncodingLength Opaconst_null = 1 -opcodeEncodingLength Opreturn = 1 -opcodeEncodingLength Opireturn = 1 -opcodeEncodingLength Opareturn = 1 -opcodeEncodingLength (Opgoto _) = 3 -opcodeEncodingLength (Opsipush _) = 3 -opcodeEncodingLength (Opldc_w _) = 3 -opcodeEncodingLength (Opaload _) = 3 -opcodeEncodingLength (Opiload _) = 3 -opcodeEncodingLength (Opastore _) = 3 -opcodeEncodingLength (Opistore _) = 3 -opcodeEncodingLength (Opputfield _) = 3 -opcodeEncodingLength (OpgetField _) = 3 +opcodeEncodingLength Opiadd = 1 +opcodeEncodingLength Opisub = 1 +opcodeEncodingLength Opimul = 1 +opcodeEncodingLength Opidiv = 1 +opcodeEncodingLength Opiand = 1 +opcodeEncodingLength Opior = 1 +opcodeEncodingLength Opixor = 1 +opcodeEncodingLength Opineg = 1 +opcodeEncodingLength (Opif_icmplt _) = 3 +opcodeEncodingLength (Opif_icmple _) = 3 +opcodeEncodingLength (Opif_icmpgt _) = 3 +opcodeEncodingLength (Opif_icmpge _) = 3 +opcodeEncodingLength (Opif_icmpeq _) = 3 +opcodeEncodingLength (Opif_icmpne _) = 3 +opcodeEncodingLength Opaconst_null = 1 +opcodeEncodingLength Opreturn = 1 +opcodeEncodingLength Opireturn = 1 +opcodeEncodingLength Opareturn = 1 +opcodeEncodingLength (Opinvokespecial _) = 3 +opcodeEncodingLength (Opgoto _) = 3 +opcodeEncodingLength (Opsipush _) = 3 +opcodeEncodingLength (Opldc_w _) = 3 +opcodeEncodingLength (Opaload _) = 3 +opcodeEncodingLength (Opiload _) = 3 +opcodeEncodingLength (Opastore _) = 3 +opcodeEncodingLength (Opistore _) = 3 +opcodeEncodingLength (Opputfield _) = 3 +opcodeEncodingLength (OpgetField _) = 3 class Serializable a where serialize :: a -> [Word8] @@ -139,33 +141,34 @@ instance Serializable MemberInfo where ++ concatMap serialize (memberAttributes member) instance Serializable Operation where - serialize Opiadd = [0x60] - serialize Opisub = [0x64] - serialize Opimul = [0x68] - serialize Opidiv = [0x6C] - serialize Opiand = [0x7E] - serialize Opior = [0x80] - serialize Opixor = [0x82] - serialize Opineg = [0x74] - serialize (Opif_icmplt branch) = 0xA1 : unpackWord16 branch - serialize (Opif_icmple branch) = 0xA4 : unpackWord16 branch - serialize (Opif_icmpgt branch) = 0xA3 : unpackWord16 branch - serialize (Opif_icmpge branch) = 0xA2 : unpackWord16 branch - serialize (Opif_icmpeq branch) = 0x9F : unpackWord16 branch - serialize (Opif_icmpne branch) = 0xA0 : unpackWord16 branch - serialize Opaconst_null = [0x01] - serialize Opreturn = [0xB1] - serialize Opireturn = [0xAC] - serialize Opareturn = [0xB0] - serialize (Opgoto index) = 0xA7 : unpackWord16 index - serialize (Opsipush index) = 0x11 : unpackWord16 index - serialize (Opldc_w index) = 0x13 : unpackWord16 index - serialize (Opaload index) = [0xC4, 0x19] ++ unpackWord16 index - serialize (Opiload index) = [0xC4, 0x15] ++ unpackWord16 index - serialize (Opastore index) = [0xC4, 0x3A] ++ unpackWord16 index - serialize (Opistore index) = [0xC4, 0x36] ++ unpackWord16 index - serialize (Opputfield index) = 0xB5 : unpackWord16 index - serialize (OpgetField index) = 0xB4 : unpackWord16 index + serialize Opiadd = [0x60] + serialize Opisub = [0x64] + serialize Opimul = [0x68] + serialize Opidiv = [0x6C] + serialize Opiand = [0x7E] + serialize Opior = [0x80] + serialize Opixor = [0x82] + serialize Opineg = [0x74] + serialize (Opif_icmplt branch) = 0xA1 : unpackWord16 branch + serialize (Opif_icmple branch) = 0xA4 : unpackWord16 branch + serialize (Opif_icmpgt branch) = 0xA3 : unpackWord16 branch + serialize (Opif_icmpge branch) = 0xA2 : unpackWord16 branch + serialize (Opif_icmpeq branch) = 0x9F : unpackWord16 branch + serialize (Opif_icmpne branch) = 0xA0 : unpackWord16 branch + serialize Opaconst_null = [0x01] + serialize Opreturn = [0xB1] + serialize Opireturn = [0xAC] + serialize Opareturn = [0xB0] + serialize (Opinvokespecial index) = 0xB7 : unpackWord16 index + serialize (Opgoto index) = 0xA7 : unpackWord16 index + serialize (Opsipush index) = 0x11 : unpackWord16 index + serialize (Opldc_w index) = 0x13 : unpackWord16 index + serialize (Opaload index) = [0xC4, 0x19] ++ unpackWord16 index + serialize (Opiload index) = [0xC4, 0x15] ++ unpackWord16 index + serialize (Opastore index) = [0xC4, 0x3A] ++ unpackWord16 index + serialize (Opistore index) = [0xC4, 0x36] ++ unpackWord16 index + serialize (Opputfield index) = 0xB5 : unpackWord16 index + serialize (OpgetField index) = 0xB4 : unpackWord16 index instance Serializable Attribute where serialize (CodeAttribute { attributeMaxStack = maxStack, diff --git a/src/ByteCode/ClassFile/Generator.hs b/src/ByteCode/ClassFile/Generator.hs index a482f16..866c375 100644 --- a/src/ByteCode/ClassFile/Generator.hs +++ b/src/ByteCode/ClassFile/Generator.hs @@ -201,8 +201,17 @@ comparisonOperation CompareGreaterOrEqual branchLocation = Opif_icmpge branchLoc assembleMethod :: Assembler MethodDeclaration -assembleMethod (MethodDeclaration _ _ _ (TypedStatement _ (Block statements))) (constants, ops) = - foldr assembleStatement (constants, ops) statements +assembleMethod (MethodDeclaration _ name _ (TypedStatement _ (Block statements))) (constants, ops) + | name == "" = let + (constants_a, ops_a) = foldr assembleStatement (constants, ops) statements + init_ops = [Opaload 0, Opinvokespecial 2] + in + (constants_a, init_ops ++ ops_a) + | otherwise = let + (constants_a, ops_a) = foldr assembleStatement (constants, ops) statements + init_ops = [Opaload 0] + in + (constants_a, init_ops ++ ops_a) assembleMethod (MethodDeclaration _ _ _ stmt) (_, _) = error ("Block expected for method body, got: " ++ show stmt) assembleStatement :: Assembler Statement @@ -223,9 +232,8 @@ assembleExpression (TypedExpression _ (BinaryOperation op a b)) (constants, ops) | elem op [CompareEqual, CompareNotEqual, CompareLessThan, CompareLessOrEqual, CompareGreaterThan, CompareGreaterOrEqual] = let (aConstants, aOps) = assembleExpression a (constants, ops) (bConstants, bOps) = assembleExpression b (aConstants, aOps) - current_offset = sum (map opcodeEncodingLength bOps) - cmp_op = comparisonOperation op (fromIntegral (current_offset + 10)) - cmp_ops = [cmp_op, Opsipush 1, Opgoto (fromIntegral (current_offset + 13)), Opsipush 0] + cmp_op = comparisonOperation op 9 + cmp_ops = [cmp_op, Opsipush 0, Opgoto 6, Opsipush 1] in (bConstants, bOps ++ cmp_ops) assembleExpression (TypedExpression _ (CharacterLiteral literal)) (constants, ops) = diff --git a/src/Main.hs b/src/Main.hs index c2ffd1b..c9f5c18 100644 --- a/src/Main.hs +++ b/src/Main.hs @@ -9,7 +9,7 @@ import ByteCode.ClassFile import Data.ByteString (pack, writeFile) main = do - let untypedAST = parse $ alexScanTokens "class Testklasse {void something(){return;}}" + let untypedAST = parse $ alexScanTokens "class Testklasse {Testklasse(){} boolean something(){return 5 + 8 - 12 * 22 > 9 - 2 + 3;}}" let typedAST = head (typeCheckCompilationUnit untypedAST) let abstractClassFile = classBuilder typedAST emptyClassFile let assembledClassFile = pack (serialize abstractClassFile) diff --git a/src/Typecheck.hs b/src/Typecheck.hs index 7cdc3a7..e411894 100644 --- a/src/Typecheck.hs +++ b/src/Typecheck.hs @@ -302,7 +302,7 @@ typeCheckStatement (Return expr) symtab classes = Nothing -> Nothing in case expr' of Just e' -> TypedStatement (getTypeFromExpr e') (Return (Just e')) - Nothing -> TypedStatement "Void" (Return Nothing) + Nothing -> TypedStatement "void" (Return Nothing) typeCheckStatement (StatementExpressionStatement stmtExpr) symtab classes = let stmtExpr' = typeCheckStatementExpression stmtExpr symtab classes