-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEvaluator.hs
67 lines (51 loc) · 1.94 KB
/
Evaluator.hs
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
57
58
59
60
61
62
63
64
65
66
67
module Evaluator
( module Evaluator
, module Instruction
, module Error
, module Funcs
) where
import Funcs
import Error
import Instruction
import Data.List (elem)
parseNext :: TIState -> Instruction -> Either [TIError] TIState
-- Parse a label instruction and add it's label to the list of labels
parseNext s inst@(Label str) =
if elem str (tilabels s)
then Left $ [LabelError $ mkErrStr s ["Label '", str, "' already defined"]]
else Right $ addData s [(show inst)] [str] []
-- Check if the label we're attempting to jump to exists
parseNext s inst@(Goto str) =
if elem str (tilabels s)
then Right $ addLine s [(show inst)]
else Left $ [GotoError $ mkErrStr s ["No label '", str, "' found"]]
-- Set a variable with a mathematical expression
-- Check if what we're trying to set refers to another symbol
parseNext s inst@(Set sym expr) =
Right $ addData s [(show inst)] [] [sym]
-- Parse a FOR instruction (hard issue)
parseNext s inst@(For var _ code) =
if elem var (tivars s)
then Left $ [LoopError $ mkErrStr s ["Variable '", var, "' in use already"]]
else case evaluate copyS code of
Left e -> Left $ [LoopError $ mkErrStr s ["Scope error occured"]] ++ e
Right s' -> Right $ addData s
([(show inst)] ++ (tilines s') ++ [(show End)])
(tilabels s')
(tivars s')
where copyS = TIState {
tilines = [], tilabels = [],
tivars = (tivars s), ticount = (succ $ ticount s)}
-- base parser rule
parseNext s i = Right $ addLine s [(show i)]
-- use this if you want to evaluate with a specific state
evaluate :: TIState -> [Instruction] -> Either [TIError] TIState
evaluate init ilst = ev ilst init
where ev [] s = Right s
ev (i:is) s = case parseNext s i of
Left e -> Left e
Right s' -> ev is s'
-- quicker short-hand function using the initState var
eval :: [Instruction] -> Either [TIError] TIState
eval = evaluate initState
-- end Evaluator