-
Notifications
You must be signed in to change notification settings - Fork 1
/
Eval.hs
73 lines (59 loc) · 2.75 KB
/
Eval.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
68
69
70
71
72
73
module Eval where
-- This file contains definitions for functions and operators
import Val
-- main evaluation function for operators and
-- built-in FORTH functions with no output
-- takes a string and a stack and returns the stack
-- resulting from evaluation of the function
eval :: String -> [Val] -> [Val]
-- Multiplication
-- if arguments are integers, keep result as integer
eval "*" (Integer x: Integer y:tl) = Integer (x*y) : tl
-- if any argument is float, make result a float
eval "*" (x:y:tl) = (Real $ toFloat x * toFloat y) : tl
-- any remaining cases are stacks too short
eval "*" _ = error("Stack Underflow")
eval "+" (Integer x: Integer y:tl) = Integer(x + y) : tl
eval "+" (x:y:tl) = (Real $ toFloat x + toFloat y) : tl
eval "+" _ = error("Stack Underflow")
eval "-" (Integer x: Integer y:tl) = Integer(y - x) : tl
eval "-" (x:y:tl) = (Real $ toFloat y - toFloat x) : tl
eval "-" _ = error("Stack Underflow")
eval "/" (Integer x: Integer y:tl) = Integer(y `div` x) : tl
eval "/" (x:y:tl) = (Real $ toFloat y / toFloat x) : tl
eval "/" _ = error("Stack Underflow")
eval "^" (x:y:tl) = (Real(toFloat y ** toFloat x)) : tl
eval "^" _ = error("Stack Underflow")
eval "STR" (Id x:tl) = Id(x) : tl
eval "STR" (Integer x:tl) = Id(show x) : tl
eval "STR" (Real x:tl) = Id(show x) : tl
eval "STR" _ = error("Stack Underflow")
eval "CONCAT2" (Id x: Id y:tl) = Id(y ++ x) : tl
eval "CONCAT2" (x:y:tl) = error("Wrong Data Types")
eval "CONCAT2" _ = error("Stack Underflow")
eval "CONCAT3" (Id x: Id y: Id z:tl) = Id(z ++ y ++ x) : tl
eval "CONCAT3" (x:y:z:tl) = error("Wrong Data Types")
eval "CONCAT3" _ = error("Stack Underflow")
-- Duplicate the element at the top of the stack
eval "DUP" (x:tl) = (x:x:tl)
eval "DUP" [] = error("Stack Underflow")
-- this must be the last rule
-- it assumes that no match is made and preserves the string as argument
eval s l = Id s : l
-- variant of eval with output
-- state is a stack and string pair
evalOut :: String -> ([Val], String) -> ([Val], String)
-- print element at the top of the stack
evalOut "." (Id x:tl, out) = (tl, out ++ x)
evalOut "." (Integer i:tl, out) = (tl, out ++ (show i))
evalOut "." (Real x:tl, out) = (tl, out ++ (show x))
evalOut "CR" (tl, out) = (tl, out ++ "\n")
--evalOut "EMIT" (Integer i:tl, out) = (tl, out ++ [toEnum i :: Char])
evalOut "EMIT" (Integer i:tl, out) = if(i `elem` [0..127]) then (tl, out ++ [toEnum i :: Char]) else error "Integer Out of Range"
evalOut "EMIT" (Real x:tl, out) = error "Wrong Data Type"
evalOut "EMIT" (Id x:tl, out) = error "Wrong Data Type"
evalOut "EMIT" ([], _) = error "Stack Underflow"
evalOut "." ([], _) = error "Stack Underflow"
-- this has to be the last case
-- if no special case, ask eval to deal with it and propagate output
evalOut op (stack, out) = (eval op stack, out)