Skip to content

Commit 68d44fe

Browse files
committed
release(v1.2): Growing trees
2 parents e87a872 + ff25d24 commit 68d44fe

39 files changed

+782
-538
lines changed

.gitattributes

Lines changed: 0 additions & 1 deletion
This file was deleted.

Kroha.cabal

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cabal-version: 1.12
55
-- see: https://github.com/sol/hpack
66

77
name: Kroha
8-
version: 1.1.1.0
8+
version: 1.2.2.0
99
description: Please see the README on GitHub at <https://github.com/vorotynsky/Kroha#readme>
1010
homepage: https://github.com/vorotynsky/Kroha#readme
1111
bug-reports: https://github.com/vorotynsky/Kroha/issues
@@ -40,8 +40,10 @@ executable Kroha
4040
src
4141
build-depends:
4242
base >=4.7 && <5
43+
, comonad >=5 && <5.1
4344
, containers ==0.6.*
4445
, extra >=1.0 && <1.8
46+
, hashmap >=1.0.0 && <1.4
4547
, parsec >=3.1.0 && <=3.1.14.0
4648
default-language: Haskell2010
4749

@@ -69,7 +71,9 @@ test-suite Kroha-tests
6971
Diff >=0.2 && <0.5
7072
, HUnit ==1.6.*
7173
, base >=4.7 && <5
74+
, comonad >=5 && <5.1
7275
, containers ==0.6.*
7376
, extra >=1.0 && <1.8
77+
, hashmap >=1.0.0 && <1.4
7478
, parsec >=3.1.0 && <=3.1.14.0
7579
default-language: Haskell2010

package.yaml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: Kroha
2-
version: 1.1.1.0
2+
version: 1.2.2.0
33
github: "vorotynsky/Kroha"
44
license: GPL-3
55
author: "Vorotynsky Maxim"
@@ -23,6 +23,8 @@ dependencies:
2323
- containers >= 0.6 && < 0.7
2424
- parsec >= 3.1.0 && <= 3.1.14.0
2525
- extra >= 1.0 && < 1.8
26+
- comonad >= 5 && < 5.1
27+
- hashmap >= 1.0.0 && < 1.4
2628

2729
executables:
2830
Kroha:

src/Kroha.hs

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,36 @@
1-
module Kroha where
1+
module Kroha (kroha) where
22

3-
import Control.Monad.Zip (mzip)
43
import Data.Bifunctor (first)
5-
import Data.Tree (Tree (..))
4+
import Data.Foldable (toList)
5+
import Data.HashMap (fromList, lookup)
66

7+
import Kroha.Ast (NodeId, Program, genId, pzip, pzip3)
8+
import Kroha.Backends.Common (runBackend, typeConfig)
9+
import Kroha.Backends.Nasm (nasm)
10+
import Kroha.Errors (Result, showErrors)
11+
import Kroha.Instructions (instructions)
712
import Kroha.Parser (parse)
8-
import Kroha.Ast (FrameElement (Instructions), selectorProg)
9-
import Kroha.Scope (linkProgram, linksTree)
10-
import Kroha.Types (resolve, typeCastsTree, TypeConfig(..))
13+
import Kroha.Scope (linkProgram)
1114
import Kroha.Stack (stack)
12-
import Kroha.Instructions (instructions)
13-
import Kroha.Backends.Common (runBackend, Backend(typeConfig))
14-
import Kroha.Backends.Nasm (nasm)
15+
import Kroha.Types (resolve, typeCastsTree)
16+
17+
18+
compile :: Program NodeId -> Result String
19+
compile program = do
20+
scopes <- linkProgram program
21+
let tc = typeConfig nasm
22+
casts <- typeCastsTree tc scopes
23+
types <- resolve tc (pzip program casts)
24+
let stackRanges = stack tc program
25+
let prepared = instructions (pzip3 stackRanges (fmap snd scopes) program)
26+
return (runBackend nasm prepared)
27+
28+
kroha :: String -> String -> Either String String
29+
kroha name src =
30+
case parse name src of
31+
Left err -> Left err
32+
Right parsed -> first (showErrors (`Data.HashMap.lookup` rangeTable)) $ compile prog
33+
where prog = genId parsed
34+
rangeTable = fromList $ toList $ pzip prog parsed
1535

1636

17-
kroha :: String -> Either String String
18-
kroha src = first show compile
19-
where compile = do
20-
program <- parse src
21-
scopes <- linkProgram program
22-
let programTree = Node (Instructions []) (selectorProg (const $ Instructions []) id program)
23-
let tc = (typeConfig nasm)
24-
casts <- (typeCastsTree tc $ mzip (linksTree program) scopes)
25-
types <- resolve tc casts
26-
let stackRanges = stack tc program
27-
let prepared = instructions stackRanges scopes program
28-
return (runBackend nasm prepared)

src/Kroha/Ast.hs

Lines changed: 107 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
-- Copyright (c) 2020 Vorotynsky Maxim
1+
-- Copyright (c) 2020 - 2021 Vorotynsky Maxim
2+
3+
{-# LANGUAGE DeriveTraversable #-}
4+
{-# LANGUAGE RankNTypes #-}
25

36
module Kroha.Ast where
47

8+
import Control.Comonad
59
import Data.Tree
610
import Data.List (mapAccumR)
11+
import Control.Monad.Zip (mzipWith)
712

813
type VariableName = String
914
type RegisterName = String
@@ -35,65 +40,115 @@ data LocalVariable
3540
deriving (Show, Eq)
3641

3742
data Comparator
38-
= Equals | NotEquals
39-
| Greater | Less
43+
= Equals | NotEquals
44+
| Greater | Less
4045
deriving (Show, Eq)
4146

4247
newtype Condition = Condition (RValue, Comparator, RValue)
4348
deriving (Show, Eq)
4449

45-
data FrameElement
46-
= Instructions [FrameElement]
47-
| VariableDeclaration LocalVariable
48-
| If Label Condition FrameElement FrameElement
49-
| Loop Label FrameElement
50-
| Break Label
51-
| Call Label [RValue]
52-
| Assignment LValue RValue
53-
| Inline InlinedCode
54-
deriving (Show, Eq)
55-
56-
57-
data Declaration
58-
= Frame Label FrameElement
59-
| GlobalVariable VariableName TypeName Literal
60-
| ConstantVariable VariableName TypeName Literal
61-
| ManualFrame Label InlinedCode
62-
| ManualVariable VariableName TypeName InlinedCode
63-
deriving (Show, Eq)
64-
65-
newtype Program = Program [Declaration]
66-
deriving (Show, Eq)
67-
68-
type Selector a = FrameElement -> a
69-
70-
childs :: FrameElement -> [FrameElement]
71-
childs (Instructions xs) = xs
72-
childs (VariableDeclaration x) = []
73-
childs (If _ _ b e) = [b, e]
74-
childs (Loop _ b) = [b]
75-
childs (Break _) = []
76-
childs (Call _ _) = []
77-
childs (Assignment _ _) = []
78-
childs (Inline _) = []
79-
80-
selector :: Selector a -> FrameElement -> Tree a
50+
data FrameElement d
51+
= Instructions [FrameElement d] d
52+
| VariableDeclaration LocalVariable d
53+
| If Label Condition (FrameElement d) (FrameElement d) d
54+
| Loop Label (FrameElement d) d
55+
| Break Label d
56+
| Call Label [RValue] d
57+
| Assignment LValue RValue d
58+
| Inline InlinedCode d
59+
deriving (Show, Eq, Functor, Foldable, Traversable)
60+
61+
62+
data Declaration d
63+
= Frame Label (FrameElement d) d
64+
| GlobalVariable VariableName TypeName Literal d
65+
| ConstantVariable VariableName TypeName Literal d
66+
| ManualFrame Label InlinedCode d
67+
| ManualVariable VariableName TypeName InlinedCode d
68+
deriving (Show, Eq, Functor, Foldable, Traversable)
69+
70+
data Program d = Program [Declaration d] d
71+
deriving (Show, Eq, Functor, Foldable, Traversable)
72+
73+
childs :: FrameElement d -> [FrameElement d]
74+
childs (Instructions xs _) = xs
75+
childs (VariableDeclaration x _) = []
76+
childs (If _ _ b e _) = [b, e]
77+
childs (Loop _ b _) = [b]
78+
childs (Break _ _) = []
79+
childs (Call _ _ _) = []
80+
childs (Assignment _ _ _) = []
81+
childs (Inline _ _) = []
82+
83+
getDeclData :: Declaration d -> d
84+
getDeclData (Frame _ _ d) = d
85+
getDeclData (GlobalVariable _ _ _ d) = d
86+
getDeclData (ConstantVariable _ _ _ d) = d
87+
getDeclData (ManualFrame _ _ d) = d
88+
getDeclData (ManualVariable _ _ _ d) = d
89+
90+
91+
92+
selector :: (FrameElement d -> a) -> FrameElement d -> Tree a
8193
selector s = unfoldTree (\e -> (s e, childs e))
8294

83-
selectorM :: Monad m => Selector (m a) -> FrameElement -> m (Tree a)
84-
selectorM s = unfoldTreeM (\e -> s e >>= (\x -> return (x, childs e)))
85-
86-
87-
selectorProg :: (Declaration -> a) -> Selector a -> Program -> Forest a
88-
selectorProg df sf (Program declarations) = fmap mapper declarations
89-
where mapper d@(Frame _ frame) = Node (df d) [selector sf frame]
90-
mapper declaration = Node (df declaration) []
95+
selectorProg :: (Declaration d -> a) -> (FrameElement d -> a) -> Program d -> Forest a
96+
selectorProg df sf (Program declarations _) = fmap mapper declarations
97+
where mapper d@(Frame _ frame _) = Node (df d) [selector sf frame]
98+
mapper declaration = Node (df declaration) []
9199

92100

93101
type NodeId = Int
94102

95-
genId :: Tree a -> Tree NodeId
96-
genId = snd . mapAccumR (\ac b -> (ac + 1, ac)) 0
97-
98-
progId :: Program -> Tree NodeId
99-
progId program = genId $ Node () (selectorProg (const ()) (const ()) program)
103+
genId :: Program d -> Program NodeId
104+
genId (Program decls _) = Program (snd $ mapAccumR declId 1 decls) 0
105+
where genId'' = mapAccumR (\ac b -> (ac + 1, ac))
106+
declId begin (Frame l fe _) = let (acc, fe') = genId'' (begin + 1) fe in (acc, Frame l fe' begin)
107+
declId begin d = (begin + 1, d $> begin)
108+
109+
progId :: Program d -> Tree NodeId
110+
progId program = Node 0 $ selectorProg getDeclData extract (genId program)
111+
112+
instance Comonad FrameElement where
113+
duplicate node@(Instructions c _) = Instructions (map duplicate c) node
114+
duplicate node@(VariableDeclaration v _) = VariableDeclaration v node
115+
duplicate node@(If l c i e _) = If l c (duplicate i) (duplicate e) node
116+
duplicate node@(Loop l b _) = Loop l (duplicate b) node
117+
duplicate node@(Break l _) = Break l node
118+
duplicate node@(Call l a _) = Call l a node
119+
duplicate node@(Assignment l r _) = Assignment l r node
120+
duplicate node@(Inline c _) = Inline c node
121+
122+
extract (Instructions _ d) = d
123+
extract (VariableDeclaration _ d) = d
124+
extract (If _ _ _ _ d) = d
125+
extract (Loop _ _ d) = d
126+
extract (Break _ d) = d
127+
extract (Call _ _ d) = d
128+
extract (Assignment _ _ d) = d
129+
extract (Inline _ d) = d
130+
131+
tzip :: FrameElement a -> FrameElement b -> FrameElement (a, b)
132+
tzip (Instructions ca _a) (Instructions cb _b) = Instructions (uncurry tzip <$> zip ca cb) (_a, _b)
133+
tzip (VariableDeclaration va _a) (VariableDeclaration vb _b) | va == vb = VariableDeclaration va (_a, _b)
134+
tzip (If la ca ia ea _a) (If lb cb ib eb _b) | (la, ca) == (lb, cb) = If la ca (tzip ia ib) (tzip ea eb) (_a, _b)
135+
tzip (Loop la ba _a) (Loop lb bb _b) | la == lb = Loop la (tzip ba bb) (_a, _b)
136+
tzip (Break la _a) (Break lb _b) | la == lb = Break la (_a, _b)
137+
tzip (Call la aa _a) (Call lb ab _b) | (la, aa) == (lb, ab) = Call la aa (_a, _b)
138+
tzip (Assignment la ra _a) (Assignment lb rb _b) | (la, ra) == (lb, rb) = Assignment la ra (_a, _b)
139+
tzip (Inline ca _a) (Inline cb _b) | ca == cb = Inline ca (_a, _b)
140+
tzip _ _ = error "can't zip different frame elements"
141+
142+
dzip :: Declaration a -> Declaration b -> Declaration (a, b)
143+
dzip (Frame la fea _a) (Frame lb feb _b) | la == lb = Frame la (tzip fea feb) (_a, _b)
144+
dzip (GlobalVariable va ta la _a) (GlobalVariable vb tb lb _b) | (va, ta, la) == (vb, tb, lb) = GlobalVariable va ta la (_a, _b)
145+
dzip (ConstantVariable va ta la _a) (ConstantVariable vb tb lb _b) | (va, ta, la) == (vb, tb, lb) = ConstantVariable va ta la (_a, _b)
146+
dzip (ManualFrame la ca _a) (ManualFrame lb cb _b) | (la, ca) == (lb, cb) = ManualFrame la ca (_a, _b)
147+
dzip (ManualVariable va ta ca _a) (ManualVariable vb tb cb _b) | (va, ta, ca) == (vb, tb, cb) = ManualVariable va ta ca (_a, _b)
148+
dzip _ _ = error "can't zip different declarations"
149+
150+
pzip :: Program a -> Program b -> Program (a, b)
151+
pzip (Program da _a) (Program db _b) = Program (mzipWith dzip da db) (_a, _b)
152+
153+
pzip3 :: Program a -> Program b -> Program c -> Program (a, b, c)
154+
pzip3 a b c = fmap (\((a, b), c) -> (a, b, c)) (pzip (pzip a b) c)

src/Kroha/Backends/Common.hs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import Kroha.Ast (Declaration(..))
44
import Kroha.Types (TypeConfig)
55
import Kroha.Instructions (Instruction(Body), Section)
66

7-
import Control.Monad (join)
7+
import Control.Monad (join, void)
88
import Data.Tree (Tree(..))
99
import Data.Char (isSpace)
1010
import Data.Semigroup (Min(Min, getMin))
@@ -16,7 +16,7 @@ data Backend = Backend
1616
, bodyWrap :: [String] -> [String]
1717
, indent :: String
1818
, section :: Section -> String -> String
19-
, declaration :: Declaration -> [String] -> String }
19+
, declaration :: Declaration () -> [String] -> String }
2020

2121

2222
makeFix :: Backend -> Tree [Instruction] -> [String]
@@ -30,14 +30,14 @@ unindentManual code = fmap (drop minIndent) lined
3030
filterEmpty = filter (not . null . filter (not . isSpace))
3131
minIndent = getMin . foldMap (Min . length . takeWhile isSpace) . filterEmpty $ lined
3232

33-
backendDeclaration :: Backend -> Declaration -> Tree [Instruction] -> String
34-
backendDeclaration b decl@(Frame _ frame) ti = declaration b decl (makeFix b ti)
35-
backendDeclaration b decl@(GlobalVariable _ _ l) _ = declaration b decl []
36-
backendDeclaration b decl@(ConstantVariable _ _ l) _ = declaration b decl []
37-
backendDeclaration b decl@(ManualFrame _ c) _ = declaration b decl (unindentManual c)
38-
backendDeclaration b decl@(ManualVariable _ _ c) _ = declaration b decl (unindentManual c)
33+
backendDeclaration :: Backend -> Declaration () -> Tree [Instruction] -> String
34+
backendDeclaration b decl@(Frame _ frame _) ti = declaration b decl (makeFix b ti)
35+
backendDeclaration b decl@(GlobalVariable _ _ l _) _ = declaration b decl []
36+
backendDeclaration b decl@(ConstantVariable _ _ l _) _ = declaration b decl []
37+
backendDeclaration b decl@(ManualFrame _ c _) _ = declaration b decl (unindentManual c)
38+
backendDeclaration b decl@(ManualVariable _ _ c _) _ = declaration b decl (unindentManual c)
3939

40-
runBackend :: Backend -> [(Section, Declaration, Tree [Instruction])] -> String
40+
runBackend :: Backend -> [(Section, Declaration d, Tree [Instruction])] -> String
4141
runBackend backend = join . fmap (mapper)
42-
where mapper (s, d, i) = section backend s (backendDeclaration backend d i)
42+
where mapper (s, d, i) = section backend s (backendDeclaration backend (void d) i)
4343

src/Kroha/Backends/Nasm.hs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,13 +57,13 @@ nasmSection :: Section -> String -> String
5757
nasmSection section body = header <> body <> "\n\n"
5858
where header = "section ." ++ section ++ "\n"
5959

60-
nasmDeclaration :: Declaration -> [String] -> String
61-
nasmDeclaration (Frame l _) body = l ++ ":\n" ++ intercalate "\n" body ++ "\nleave\nret"
62-
nasmDeclaration (ManualVariable v _ _) [body] = v ++ ": " ++ body ++ "\n"
63-
nasmDeclaration (ManualFrame l _) body = l ++ ":\n" ++ intercalate "\n" (fmap ((++) " ") body)
64-
nasmDeclaration (ManualVariable v _ _) body = v ++ ":\n" ++ intercalate "\n" (fmap ((++) " ") body)
65-
nasmDeclaration (GlobalVariable n t (IntegerLiteral l)) _ = n ++ ": " ++ nasmTypeG t ++ " " ++ show l
66-
nasmDeclaration (ConstantVariable n t (IntegerLiteral l)) _ = n ++ ": " ++ nasmTypeG t ++ " " ++ show l
60+
nasmDeclaration :: Declaration d -> [String] -> String
61+
nasmDeclaration (Frame l _ _) body = l ++ ":\n" ++ intercalate "\n" body ++ "\nleave\nret"
62+
nasmDeclaration (ManualVariable v _ _ _) [body] = v ++ ": " ++ body ++ "\n"
63+
nasmDeclaration (ManualFrame l _ _) body = l ++ ":\n" ++ intercalate "\n" (fmap ((++) " ") body)
64+
nasmDeclaration (ManualVariable v _ _ _) body = v ++ ":\n" ++ intercalate "\n" (fmap ((++) " ") body)
65+
nasmDeclaration (GlobalVariable n t (IntegerLiteral l) _) _ = n ++ ": " ++ nasmTypeG t ++ " " ++ show l
66+
nasmDeclaration (ConstantVariable n t (IntegerLiteral l) _) _ = n ++ ": " ++ nasmTypeG t ++ " " ++ show l
6767

6868
litType :: Literal -> Result TypeId
6969
litType l@(IntegerLiteral x) | x >= 0 && x < 65536 = Right 2

0 commit comments

Comments
 (0)