summaryrefslogtreecommitdiff
path: root/app/Compiler.hs
blob: 3c98d70925983741f9bcaea499a7ba75e11194e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
module Compiler where

import Data.Char (isUpper)
import Data.Containers.ListUtils (nubOrd)
import Data.List (elemIndex)
import qualified Data.Map as M

import Code (Code, Datum(..), Instr(..))
import IR (Id(..), PrlgInt(..), StrTable(..))

varname :: String -> Bool
varname ('_':_) = True
varname (c:_) = isUpper c
varname _ = False

varIds :: StrTable -> PrlgInt -> [Int]
varIds st (CallI _ xs) = nubOrd $ concatMap (varIds st) xs
varIds (StrTable _ _ st) (LiteralI x)
  | Just s <- st M.!? x
  , varname s = [x]
  | otherwise = []

variablizePrlg :: Int -> [Int] -> PrlgInt -> PrlgInt
variablizePrlg void vs (CallI id ps) =
  CallI id $ map (variablizePrlg void vs) ps
variablizePrlg void vs (LiteralI i)
  | i == void = VoidI
  | Just idx <- elemIndex i vs = VarI idx i
  | otherwise = LiteralI i

compileGoals :: Id -> Int -> PrlgInt -> [Code]
compileGoals andop cut = go
  where
    go p@(CallI x args)
      | x == andop = concatMap go args
    go p@(LiteralI x)
      | x == cut = [[Cut]]
    go x = [compileGoal x]

compileGoal :: PrlgInt -> Code
compileGoal (LiteralI x) = [U (Struct $ Id x 0)]
compileGoal x = compileArg x

compileArg :: PrlgInt -> Code
compileArg (CallI x args) = U (Struct x) : concatMap compileArg args
compileArg (LiteralI x) = [U (Atom x)]
compileArg (VarI x i) = [U (LocalRef x i)]
compileArg (VoidI) = [U VoidRef]

seqGoals :: [Code] -> Code
seqGoals [] = [NoGoal]
seqGoals [[Cut]] = [Cut, NoGoal]
seqGoals [x] = [Goal] ++ x ++ [LastCall]
seqGoals [x, [Cut]] = [Goal] ++ x ++ [LastCall, Cut]
seqGoals ([Cut]:xs) = [Cut] ++ seqGoals xs
seqGoals (x:xs) = [Goal] ++ x ++ [Call] ++ seqGoals xs