diff --git a/lib/Codegen/Codegen.hs b/lib/Codegen/Codegen.hs index 73e415a..5564253 100644 --- a/lib/Codegen/Codegen.hs +++ b/lib/Codegen/Codegen.hs @@ -74,6 +74,7 @@ data CodegenErrorType | UnsupportedWhileDefinition AT.Expr | VariableNotFound String | UnsupportedFunctionCall String + | UnsupportedStructureAccess AT.Expr | ContinueOutsideLoop | BreakOutsideLoop deriving (Show) @@ -102,6 +103,7 @@ showErrorType err = case err of UnsupportedWhileDefinition expr -> "Invalid while loop: " ++ show expr VariableNotFound name -> "Variable not found: " ++ name UnsupportedFunctionCall name -> "Invalid function call: " ++ name + UnsupportedStructureAccess expr -> "Invalid structure access: " ++ show expr ContinueOutsideLoop -> "Continue statement outside loop" BreakOutsideLoop -> "Break statement outside loop" @@ -444,15 +446,34 @@ generateArrayAccess expr = -- | Generate LLVM code for struct access. generateStructAccess :: (MonadCodegen m) => AT.Expr -> m AST.Operand -generateStructAccess (AT.StructAccess loc (AT.Var _ name (AT.TStruct _ fields)) field) = do +generateStructAccess (AT.StructAccess loc (AT.StructAccess _ structExpr (AT.Var nestedStructNameLoc nestedStructName _)) (AT.Var innerFieldLoc innerFieldName innerFieldType)) = do + case structExpr of + AT.Var _ _ (AT.TStruct _ structFields) -> do + structPtr <- getStructFieldPointer structExpr nestedStructName + let nestedStructType = M.fromJust $ L.find ((== nestedStructName) . fst) structFields + nestedStructIndex <- case nestedStructType of + (_, AT.TStruct _ innerFields) -> return $ fromIntegral $ M.fromJust $ L.findIndex ((== innerFieldName) . fst) innerFields + _ -> E.throwError $ CodegenError nestedStructNameLoc $ UnsupportedStructureAccess (AT.Var innerFieldLoc innerFieldName innerFieldType) + innerFieldPtr <- I.gep structPtr [IC.int32 0, IC.int32 nestedStructIndex] + I.load innerFieldPtr 0 + -- AT.StructAccess loc expr field -> do + _ -> E.throwError $ CodegenError loc $ UnsupportedStructureAccess structExpr +generateStructAccess (AT.StructAccess _ structExpr (AT.Var _ fieldName _)) = do + fieldPtr <- getStructFieldPointer structExpr fieldName + I.load fieldPtr 0 +generateStructAccess expr = E.throwError $ CodegenError (U.getLoc expr) $ UnsupportedDefinition expr + +getStructFieldPointer :: (MonadCodegen m) => AT.Expr -> String -> m AST.Operand +getStructFieldPointer (AT.Var loc name (AT.TStruct _ fields)) fieldName = do maybeVar <- getVar name ptr <- case maybeVar of Just structPtr -> return structPtr Nothing -> E.throwError $ CodegenError loc $ VariableNotFound name - let fieldIndex = fromIntegral $ M.fromJust $ L.findIndex ((== field) . fst) fields - fieldPtr <- I.gep ptr [IC.int32 0, IC.int32 fieldIndex] - I.load fieldPtr 0 -generateStructAccess expr = E.throwError $ CodegenError (U.getLoc expr) $ UnsupportedDefinition expr + I.gep ptr [IC.int32 0, IC.int32 (findStructFieldIndex fields fieldName)] +getStructFieldPointer expr _ = E.throwError $ CodegenError (U.getLoc expr) $ UnsupportedDefinition expr + +findStructFieldIndex :: [(String, AT.Type)] -> String -> Integer +findStructFieldIndex fields' name' = fromIntegral $ M.fromJust $ L.findIndex ((== name') . fst) fields' -- | Generate LLVM code for type casts. generateCast :: (MonadCodegen m) => AT.Expr -> m AST.Operand