Skip to content

Commit ecaa904

Browse files
committed
release(v0.3): program scope
2 parents f4e65cc + d9db6a9 commit ecaa904

File tree

11 files changed

+196
-82
lines changed

11 files changed

+196
-82
lines changed

HLasm.cabal

Lines changed: 1 addition & 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: HLasm
8-
version: 0.2.0.0
8+
version: 0.3.0.0
99
description: Please see the README on GitHub at <https://github.com/vorotynsky/HLasm#readme>
1010
homepage: https://github.com/vorotynsky/HLasm#readme
1111
bug-reports: https://github.com/vorotynsky/HLasm/issues

app/Main.hs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import HLasm.Parser
1111
import HLasm.Scope (semantic)
1212
import HLasm.Types (typeCheck)
1313
import HLasm.Frame (StackFrame(Root), buildStackFrames)
14-
import HLasm.Instructions (instructions, BackEnd(..), runBackend)
14+
import HLasm.Instructions (program, BackEnd(..), runBackend)
1515
import HLasm.Backend.Nasm
1616

1717
parseAll :: String -> String
@@ -22,8 +22,8 @@ parseAll = get . first show . pipeline
2222
_ <- typeCheck semantic
2323
stack <- Right $ (buildStackFrames Root) parsed
2424
tree <- Right $ mzipWith (\(e, v, l) (_, sf) -> (e, v, l, sf)) semantic stack
25-
instructions <- instructions tree
26-
runBackend nasm instructions
25+
objProg <- program tree
26+
runBackend nasm objProg
2727

2828
main :: IO ()
2929
main = do

package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: HLasm
2-
version: 0.2.0.0
2+
version: 0.3.0.0
33
github: "vorotynsky/HLasm"
44
license: GPL-3
55
author: "Vorotynsky Maxim"

src/HLasm/Ast.hs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
module HLasm.Ast where
44

55
import Data.Tree
6+
import Data.Maybe
67

78
data Type = Type
89
{ typeName :: String
@@ -20,15 +21,6 @@ data CompareType =
2021
| Less
2122
deriving (Show, Eq)
2223

23-
data HLValuable =
24-
Variable (VariableName, Type)
25-
| Register (VariableName, RegisterName)
26-
deriving (Show, Eq)
27-
28-
valuableName :: HLValuable -> VariableName
29-
valuableName (Variable (name, _)) = name
30-
valuableName (Register (name, _)) = name
31-
3224
data HLValue =
3325
NameValue VariableName
3426
| IntegerValue Int
@@ -44,8 +36,14 @@ data Condition = Condition (HLValue, CompareType, HLValue)
4436
deriving (Show, Eq)
4537

4638
data HLElement =
47-
InstructionSet
48-
| VariableDeclaration HLValuable
39+
Program
40+
| InstructionSet
41+
| RegisterDeclaration VariableName RegisterName
42+
| VariableDeclaration VariableName Type
43+
| GlobalVarDeclaration VariableName Type HLValue
44+
| ConstVarDeclaration VariableName Type HLValue
45+
| FakeVariable VariableName
46+
| FakeFrame Label
4947
| Frame (Maybe Label)
5048
| If Label
5149
| IfBranch (Maybe Condition)
@@ -57,6 +55,19 @@ data HLElement =
5755
| AssemblyCall String
5856
deriving (Show, Eq)
5957

58+
getValuableName :: HLElement -> Maybe VariableName
59+
getValuableName (VariableDeclaration name _ ) = Just name
60+
getValuableName (RegisterDeclaration name _ ) = Just name
61+
getValuableName (GlobalVarDeclaration name _ _) = Just name
62+
getValuableName (ConstVarDeclaration name _ _) = Just name
63+
getValuableName _ = Nothing
64+
65+
isVariable :: HLElement -> Bool
66+
isVariable = isJust . getValuableName
67+
68+
variableName :: HLElement -> VariableName
69+
variableName = fromJust . getValuableName
70+
6071
usedVariables :: HLElement -> [VariableName]
6172
usedVariables (IfBranch (Just (Condition(left, _, right)))) = name left ++ name right
6273
where name (NameValue name) = [name]

src/HLasm/Backend/Nasm.hs

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,39 @@
22

33
module HLasm.Backend.Nasm (nasm) where
44

5-
import HLasm.Ast (CompareType (..))
5+
import Data.Char
6+
7+
import HLasm.Ast (CompareType (..), Type(..))
8+
import HLasm.Error
69
import HLasm.Frame
7-
import HLasm.Instructions
10+
import HLasm.Instructions hiding (program)
811

912
bytes :: Int -> Int
1013
bytes x = ceiling ((toEnum x) / 8)
1114

12-
choosePtr :: Int -> String
13-
choosePtr = f . bytes
14-
where f 1 = "BYTE"
15-
f 2 = "WORD"
16-
f 4 = "DWORD"
15+
data DataType = Byte | Word | Dword
16+
deriving (Show, Eq)
17+
18+
uname = fmap toUpper . show
19+
20+
dname Byte = "DB"
21+
dname Word = "DW"
22+
dname Dword = "DD"
23+
24+
datatype :: Int -> DataType
25+
datatype = f . bytes
26+
where f 1 = Byte
27+
f 2 = Word
28+
f 4 = Dword
1729
f n = error ("undefined data size: " ++ show n)
1830

31+
toDatatype :: Type -> DataType
32+
toDatatype = let size (Type _ (Just s)) = s in datatype . size
33+
1934
target :: Target -> String
2035
target (NamedTarget name) = name
2136
target (Register reg) = reg
22-
target (FrameVar (offset, size, _)) = choosePtr size ++ " [ebp-" ++ (show $ bytes (offset + size)) ++ "]"
37+
target (FrameVar (offset, size, _)) = (uname . datatype) size ++ " [bp-" ++ (show $ bytes (offset + size)) ++ "]"
2338
target (ConstantTarget const) = show const
2439

2540
instr2arg :: String -> Target -> Target -> String
@@ -30,7 +45,7 @@ size (Root) = 0
3045
size (Fluent _) = 0
3146
size (StackFrame _ x) = bytes $ frameSize x
3247

33-
frame f = ["push ebp", "mov ebp, esp", "sub esp, " ++ (show . size $ f)]
48+
frame f = ["push bp", "mov bp, sp", "sub sp, " ++ (show . size $ f)]
3449

3550
instruction :: Instructions -> [String]
3651
instruction (PureAsm str) = [str]
@@ -46,13 +61,26 @@ instruction (Jump lbl (Just Equals)) = ["je " ++ lbl]
4661
instruction (Jump lbl (Just NotEquals)) = ["jne " ++ lbl]
4762
instruction (Jump lbl (Just Greater)) = ["jg " ++ lbl]
4863
instruction (Jump lbl (Just Less)) = ["jl " ++ lbl]
49-
instruction (Call lbl args size) = (fmap push . reverse $ args) ++ ["call " ++ lbl, "add esp, " ++ show (bytes size)]
64+
instruction (Call lbl args size) = (fmap push . reverse $ args) ++ ["call " ++ lbl, "add sp, " ++ show (bytes size)]
5065
where push x = "push " ++ (target x)
5166

67+
variable :: Variable -> String
68+
variable (Variable n t v)= n ++ ": " ++ (dname . toDatatype) t ++ " " ++ show v
69+
5270
join :: String -> [String] -> String
5371
join s [] = ""
5472
join s [x] = x
5573
join s (x:xs) = x ++ s ++ join s xs
5674

75+
sectionHeader header = Right . join "\n" . ((:) ("section ." ++ header))
76+
77+
section :: Section -> Result String
78+
section (Text x) = sectionHeader "text\n" . concat $ fmap instruction x
79+
section (Data x) = sectionHeader "data" $ fmap variable x
80+
section (Constants x) = sectionHeader "rodata" $ fmap variable x
81+
82+
program :: ObjProgram -> Result String
83+
program (ObjProgram sections) = fmap (join "\n\n") . traverse section $ sections
84+
5785
nasm :: BackEnd
58-
nasm = BackEnd (\x -> Right . join "\n" . concat $ fmap instruction x)
86+
nasm = BackEnd program

src/HLasm/Error.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ data Error =
1111
| VariableNotFound VariableName
1212
| LabelNotFound Label
1313
| IncompatibleTypes (HLValue, HLValue)
14+
| GlobalVariableInFrame VariableName
1415
deriving (Eq)
1516

1617
type Result a = Either Error a
1718

1819
instance Show Error where
1920
show (StringError msg) = "error: " ++ msg ++ ".\n"
20-
show (VariableNotFound name) = "scope error: variable \'" ++ name ++ "\' not found.\n"
21-
show (LabelNotFound label) = "scope error: label \'" ++ label ++ "\' not found.\n"
21+
show (VariableNotFound name) = "scope error: a variable \'" ++ name ++ "\' not found.\n"
22+
show (LabelNotFound label) = "scope error: a label \'" ++ label ++ "\' not found.\n"
2223
show (IncompatibleTypes (left, right)) =
2324
"type error: incompatible types between \'" ++ show left ++ "\' and \'" ++ show right ++ "\'.\n"
2425
show (ParseError err) = "parser error, " ++ show err
26+
show (GlobalVariableInFrame name) = "error: the global variable \'" ++ name ++ "\' isn't in the global scope.\n"

src/HLasm/Frame.hs

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
module HLasm.Frame
44
( VarFrame(..)
5-
, valueSize
5+
, stackVarSize
66
, frameSize
77
, buildFrame
88
, buildFrameTree
@@ -16,29 +16,32 @@ import Data.Tree
1616
import HLasm.Ast
1717
import HLasm.Scope hiding (Scope(Root))
1818

19-
valueSize :: HLValuable -> Int
20-
valueSize (Variable (_, t)) = size t
21-
where size (Type _ (Just s)) = s
22-
{- TODO: add support or refactor in future (on adding errors to compiler) -}
23-
size (Type _ Nothing) = error "Unsupported types without specified size"
24-
valueSize (Register (_, r)) = undefined
19+
size (Type _ (Just s)) = s
20+
{- TODO: add support or refactor in future (on adding errors to compiler) -}
21+
size (Type _ Nothing) = error "Unsupported types without specified size"
2522

26-
newtype VarFrame = VarFrame [(HLValuable, Int, Int)]
23+
stackVarSize :: HLElement -> Int
24+
stackVarSize (VariableDeclaration _ t ) = size t
25+
stackVarSize (GlobalVarDeclaration _ t _) = size t
26+
stackVarSize (ConstVarDeclaration _ t _) = size t
27+
stackVarSize (RegisterDeclaration _ r ) = 0
28+
29+
newtype VarFrame = VarFrame [(HLElement, Int, Int)]
2730
deriving (Show, Eq)
2831

2932
empty :: VarFrame
3033
empty = VarFrame []
3134

3235
frameSize :: VarFrame -> Int
33-
frameSize = foldr (+) 0 . fmap valueSize . (\(VarFrame xs) -> fmap (\(x,_,_) -> x) xs)
36+
frameSize = foldr (+) 0 . fmap stackVarSize . (\(VarFrame xs) -> fmap (\(x,_,_) -> x) xs)
3437

35-
buildFrame :: [HLValuable] -> VarFrame
36-
buildFrame xs = VarFrame $ zipWith (\v o -> (v, o, valueSize v)) xs (fmap (foldl (+) 0) . inits . fmap valueSize $ xs)
38+
buildFrame :: [HLElement] -> VarFrame
39+
buildFrame xs = VarFrame $ zipWith (\v o -> (v, o, stackVarSize v)) xs (fmap (foldl (+) 0) . inits . fmap stackVarSize $ xs)
3740

38-
frameVars :: SyntaxTree -> [HLValuable]
41+
frameVars :: SyntaxTree -> [HLElement]
3942
frameVars (Node el@(Frame _) []) = []
4043
frameVars (Node el@(Frame _) (x:_)) = frameVars x
41-
where frameVars (Node (VariableDeclaration val@(Variable _)) xs) = [val] ++ (concatMap frameVars xs)
44+
where frameVars (Node val xs) | isVariable val = [val] ++ (concatMap frameVars xs)
4245
frameVars (Node el@(Frame _) _) = []
4346
frameVars (Node _ xs) = concatMap frameVars xs
4447

@@ -66,5 +69,5 @@ findOffset (StackFrame parent vars) name
6669
| (any predicate list) = fmap (\(_, o, _) -> o) . find predicate $ list
6770
| otherwise = fmap (+ frameSize vars) $ findOffset parent name -- -> change last commit
6871
where list = (\(VarFrame xs) -> xs) vars
69-
predicate ((Variable (n, _)), _, _) | n == name = True
72+
predicate (el, _, _) | isVariable el && (variableName el) == name = True
7073
predicate _ = False

src/HLasm/Instructions.hs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22

33
module HLasm.Instructions
44
( Offset(..), Target(..), InstructionSet(..)
5-
, Instructions(..)
5+
, Instructions(..), Variable(..)
6+
, Section(..), ObjProgram(..)
67
, BackEnd(..)
78
, runBackend
8-
, instructions
9+
, program
910
) where
1011

1112
import Control.Monad.Extra (concatMapM)
@@ -40,16 +41,24 @@ data Instructions =
4041

4142
type InstructionSet = [Instructions]
4243

43-
newtype BackEnd = BackEnd (InstructionSet -> Result String)
44+
data Variable = Variable VariableName Type HLValue
45+
46+
data Section =
47+
Text InstructionSet
48+
| Data [Variable]
49+
| Constants [Variable]
50+
51+
newtype ObjProgram = ObjProgram [Section]
52+
53+
newtype BackEnd = BackEnd (ObjProgram -> Result String)
4454
runBackend (BackEnd f) x = f x
4555

4656

4757
target :: StackFrame -> VariableData -> Target
48-
target _ (VariableData (_, VariableDeclaration (HLasm.Ast.Register(_, reg)))) = HLasm.Instructions.Register reg
58+
target _ (VariableData (_, (RegisterDeclaration _ reg))) = HLasm.Instructions.Register reg
4959
target frame (VariableData (name, e)) = case findOffset frame name of
50-
Just x -> FrameVar (x, size e, name)
60+
Just x -> FrameVar (x, stackVarSize e, name)
5161
Nothing -> NamedTarget name
52-
where size (VariableDeclaration v) = valueSize v
5362

5463
findTarget :: StackFrame -> [VariableData] -> VariableName -> Target -- was a lot of checks, target garanteed be here.
5564
findTarget frame xs name = target frame . fromJust . find (\(VariableData (n, _)) -> n == name) $ xs
@@ -61,31 +70,61 @@ valuableTarget (sf, vd) (NameValue name) = findTarget sf vd name
6170
loop :: Label -> Result (InstructionSet) -> Result (InstructionSet)
6271
loop lbl i = let begin = lbl ++ "begin" in fmap (\x -> [Label begin] ++ x ++ [Jump begin Nothing, Label (lbl ++ "end")]) $ i
6372

73+
isEmptyInstruction :: HLElement -> Bool
74+
isEmptyInstruction (FakeVariable _) = True
75+
isEmptyInstruction (FakeFrame _) = True
76+
isEmptyInstruction (VariableDeclaration _ _) = True
77+
isEmptyInstruction (RegisterDeclaration _ _) = True
78+
isEmptyInstruction _ = False
79+
80+
6481
instructions :: Tree (HLElement, [VariableData], [LabelData], StackFrame) -> Result (InstructionSet)
82+
instructions (Node (el, _, _, _) _) | isEmptyInstruction el = Right []
6583
instructions (Node ((InstructionSet ), _, _, _) xs) = concatMapM instructions xs
66-
instructions (Node ((VariableDeclaration val), _, _, _) _ ) = Right []
6784
instructions (Node ((While lbl ), _, _, _) xs) = loop lbl (concatMapM instructions xs)
6885
instructions (Node ((DoWhile lbl ), _, _, _) xs) = loop lbl (concatMapM instructions xs)
6986
instructions (Node ((Break lbl ), _, _, _) _ ) = Right [Jump (lbl ++ "end") Nothing]
7087
instructions (Node ((AssemblyCall str ), _, _, _) _ ) = Right [PureAsm str]
7188
instructions (Node ((Frame lbl ), _, _, f) xs) =
7289
(\body -> [BeginFrame f lbl] ++ body ++ [EndFrame f lbl]) <$> concatMapM instructions xs
7390

91+
instructions (Node ((GlobalVarDeclaration n _ _), _, _, _) _ ) = Left (GlobalVariableInFrame n)
92+
instructions (Node ((ConstVarDeclaration n _ _), _, _, _) _ ) = Left (GlobalVariableInFrame n)
93+
7494
instructions (Node ((Assignment name (NameValue val)), d, _, f) _) = Right [Move (findTarget f d name) (findTarget f d val)]
7595
instructions (Node ((Assignment name (IntegerValue val)), d, _, f) _) = Right [Move (findTarget f d name) (ConstantTarget val)]
7696

7797
instructions (Node ((HLasm.Ast.Call lbl ns ), d, _, f) _ ) =
7898
Right [HLasm.Instructions.Call lbl (fmap (findTarget f d) ns) size]
79-
where size = foldl (+) 0 . fmap (\(VariableData (_, (VariableDeclaration d))) -> valueSize d) $ d
99+
where size = foldl (+) 0 . fmap (\(VariableData (_, d)) -> stackVarSize d) $ d
80100

81101
instructions (Node ((If lbl), _, _, _) []) = Right []
82102
instructions (Node ((If lbl), _, _, _) xs) =
83103
do (conds, bodies') <- Right $ traverse (uncurry branch) (zip [1..] xs)
84104
bodies <- fmap (concat) . sequence $ bodies'
85105
Right $ conds ++ [Jump (lbl ++ "end") Nothing] ++ bodies ++ [Label (lbl ++ "end")]
86-
87106
where condition lbl pt (Condition (left, cmp, right)) =
88107
let find = valuableTarget pt in [Compare (find left) (find right), Jump lbl (Just cmp)]
89108
wrapif i = fmap (\b -> [Label (lbl ++ show i)] ++ b ++ [Jump (lbl ++ "end") Nothing]) . concatMapM instructions
90109
branch i (Node ((IfBranch (Just cond)), d, _, f) xs) = (condition (lbl ++ show i) (f, d) cond, wrapif i xs)
91110
branch i (Node ((IfBranch Nothing), _, _, _) xs) = ([Jump (lbl ++ show i) Nothing], wrapif i xs)
111+
112+
113+
dataFilter (Node ((GlobalVarDeclaration n t v), _, _, _) _) = Just $ Variable n t v
114+
dataFilter _ = Nothing
115+
constFilter (Node ((ConstVarDeclaration n t v), _, _, _) _) = Just $ Variable n t v
116+
constFilter _ = Nothing
117+
118+
varSection ctor f xs = Right . ctor . fmap fromJust . filter isJust . fmap f $ xs
119+
120+
filterF :: [(a -> Maybe b)] -> (a -> Bool)
121+
filterF fs = foldl or (const True) . fmap ((.) (not . isJust)) $ fs
122+
where or f g x = f x && g x
123+
124+
program :: Tree (HLElement, [VariableData], [LabelData], StackFrame) -> Result ObjProgram
125+
program (Node ((Program), _, _, _) xs) =
126+
do text <- concatMapM instructions . filter (filterF [dataFilter, constFilter]) $ xs
127+
dat <- varSection Data dataFilter xs
128+
const <- varSection Constants constFilter xs
129+
Right $ ObjProgram [(Text text), dat, const]
130+
program _ = undefined

0 commit comments

Comments
 (0)