적극적인 리팩토링

3516 단어 haskelltesting
다음은 Haskell에서 공격적인 리팩토링의 작은 예입니다. 저는 소규모 스마트 계약 언어용 컴파일러의 코드베이스에 있으며 문제의 코드 생성기가 256비트 단어 크기를 가진 이더리움을 대상으로 하기 때문에 Integer 발생을 Word256 발생으로 대체하고 있습니다.

컴파일러는 원래 Integer 로 만들어졌으며 어떤 경우에는 조잡한 방식으로 만들어진 자체 Word256 로 만들어졌습니다. Integer 이것은 Haskell에서 매우 편리한 데이터 유형이기 때문에 이 경우 임의의 정밀도가 실제로 잘못되었음에도 불구하고 조잡한Word256 라이브러리를 가져오는 것보다 이 유형을 만드는 것이 더 간단해 보였기 때문입니다.

그러나 이제는 이것이 더 이상 편리하지 않으므로 Hevm이 사용하는 라이브러리이므로 Word256 라이브러리data-dword를 사용하기로 결정했습니다. largewordwide-word 대안이 있지만 현재 중요한 부분은 상호 운용성입니다.

그리고 여기에 내가 보여주고 싶은 유형 오류가 있습니다.

src/Lira/Backends/Evm/EvmCompiler.hs:695:22: error:
    • Couldn't match expected type ‘Integer’
                  with actual type ‘Data.DoubleWord.Word256’
    • In the first argument of ‘push’, namely ‘i’
      In the expression: push i
      In the expression: [push i]
    |
695 |   IntVal  i -> [push i]
    |                      ^

IntVal i는 이제 Word256를 포함하고 pushInteger용으로 설계되었으므로 유형이 더 이상 정렬되지 않습니다. push를보고 :

push :: Integer -> EvmOpcode
push = PUSHN . words'
  where
    words' :: Integer -> [Word8]
    words' i | i < 256 = [fromIntegral i]
    words' i           = words' (i `div` 256) ++ [fromIntegral $ i `mod` 256]


이 함수에는 Word256가 아닌 Integer에서 작동하지 못하도록 하는 논리가 없습니다. 사실, 기능을 변경하는 대신 유형 서명을 느슨하게 하십시오.

-push :: Integer -> EvmOpcode
+push :: Integral i => i -> EvmOpcode
 push = PUSHN . words'
   where
-    words' :: Integer -> [Word8]
+    words' :: Integral i => i -> [Word8]
     words' i | i < 256 = [fromIntegral i]
     words' i           = words' (i `div` 256) ++ [fromIntegral $ i `mod` 256]


코드베이스에서 기본 유형을 변경하는 것과 같은 공격적인 리팩터링을 수행하려면 수백 가지 변경이 필요합니다. 그러나 그들의 성격이 이와 같을 때 나는 이 변경을 안전하게 두고 다음 유형 오류로 진행할 수 있습니다.

좋은 웹페이지 즐겨찾기