+++ /dev/null
--- Copyright (c) 2000 Galois Connections, Inc.
--- All rights reserved. This software is distributed as
--- free software under the license in the file "LICENSE",
--- which is included in the distribution.
-
-module Data where
-
-import Array
-import IOExts
-
-import CSG
-import Geometry
-import Illumination
-import Primitives
-import Surface
-
--- Now the parsed (expresssion) language
-
-type Name = String
-
-type Code = [GMLToken]
-
-data GMLToken
- -- All these can occur in parsed code
- = TOp GMLOp
- | TId Name
- | TBind Name
- | TBool Bool
- | TInt Int
- | TReal Double
- | TString String
- | TBody Code
- | TArray Code
- | TApply
- | TIf
- -- These can occur in optimized/transformed code
- -- NONE (yet!)
-
-
-instance Show GMLToken where
- showsPrec p (TOp op) = shows op
- showsPrec p (TId id) = showString id
- showsPrec p (TBind id) = showString ('/' : id)
- showsPrec p (TBool bool) = shows bool
- showsPrec p (TInt i) = shows i
- showsPrec p (TReal d) = shows d
- showsPrec p (TString s) = shows s
- showsPrec p (TBody code) = shows code
- showsPrec p (TArray code) = showString "[ "
- . foldr (\ a b -> a . showChar ' ' . b) id (map shows code)
- . showString "]"
- showsPrec p (TApply) = showString "apply"
- showsPrec p (TIf) = showString "if"
-
- showList code = showString "{ "
- . foldr (\ a b -> a . showChar ' ' . b) id (map shows code)
- . showString "}"
-
-
--- Now the value language, used inside the interpreter
-
-type Stack = [GMLValue]
-
-data GMLValue
- = VBool !Bool
- | VInt !Int
- | VReal !Double
- | VString String
- | VClosure Env Code
- | VArray (Array Int GMLValue) -- FIXME: Haskell array
- -- uses the interpreter version of point
- | VPoint { xPoint :: !Double
- , yPoint :: !Double
- , zPoint :: !Double
- }
- -- these are abstract to the interpreter
- | VObject Object
- | VLight Light
- -- This is an abstract object, used by the abstract interpreter
- | VAbsObj AbsObj
-
-
--- There are only *3* basic abstract values,
--- and the combinators also.
-
-data AbsObj
- = AbsFACE
- | AbsU
- | AbsV
- deriving (Show)
-
-instance Show GMLValue where
- showsPrec p value = showString (showStkEle value)
-
-showStkEle :: GMLValue -> String
-showStkEle (VBool b) = show b ++ " :: Bool"
-showStkEle (VInt i) = show i ++ " :: Int"
-showStkEle (VReal r) = show r ++ " :: Real"
-showStkEle (VString s) = show s ++ " :: String"
-showStkEle (VClosure {}) = "<closure> :: Closure"
-showStkEle (VArray arr)
- = "<array (" ++ show (succ (snd (bounds arr))) ++ " elements)> :: Array"
-showStkEle (VPoint x y z) = "(" ++ show x
- ++ "," ++ show y
- ++ "," ++ show z
- ++ ") :: Point"
-showStkEle (VObject {}) = "<Object> :: Object"
-showStkEle (VLight {}) = "<Light> :: Object"
-showStkEle (VAbsObj vobs) = "{{ " ++ show vobs ++ "}} :: AbsObj"
-
--- An abstract environment
-
-newtype Env = Env [(Name, GMLValue)] deriving Show
-
-emptyEnv :: Env
-emptyEnv = Env []
-
-extendEnv :: Env -> Name -> GMLValue -> Env
-extendEnv (Env e) n v = Env ((n, v):e)
-
-lookupEnv :: Env -> Name -> Maybe GMLValue
-lookupEnv (Env e) n = lookup n e
-
--- All primitive operators
---
--- There is no Op_apply, Op_false, Op_true and Op_if
--- (because they appear explcitly in the rules).
-
-data GMLOp
- = Op_acos
- | Op_addi
- | Op_addf
- | Op_asin
- | Op_clampf
- | Op_cone
- | Op_cos
- | Op_cube
- | Op_cylinder
- | Op_difference
- | Op_divi
- | Op_divf
- | Op_eqi
- | Op_eqf
- | Op_floor
- | Op_frac
- | Op_get
- | Op_getx
- | Op_gety
- | Op_getz
- | Op_intersect
- | Op_length
- | Op_lessi
- | Op_lessf
- | Op_light
- | Op_modi
- | Op_muli
- | Op_mulf
- | Op_negi
- | Op_negf
- | Op_plane
- | Op_point
- | Op_pointlight
- | Op_real
- | Op_render
- | Op_rotatex
- | Op_rotatey
- | Op_rotatez
- | Op_scale
- | Op_sin
- | Op_sphere
- | Op_spotlight
- | Op_sqrt
- | Op_subi
- | Op_subf
- | Op_trace -- non standard, for debugging GML programs
- | Op_translate
- | Op_union
- | Op_uscale
- deriving (Eq,Ord,Ix,Bounded)
-
-instance Show GMLOp where
- showsPrec _ op = showString (opNameTable ! op)
-
-
-------------------------------------------------------------------------------
-
--- And how we use the op codes (there names, there interface)
-
--- These keywords include, "apply", "if", "true" and "false",
--- they are not parsed as operators, but are
--- captured by the parser as a special case.
-
-keyWords :: [String]
-keyWords = [ kwd | (kwd,_,_) <- opcodes ]
-
--- Lookup has to look from the start (or else...)
-opTable :: [(Name,GMLToken)]
-opTable = [ (kwd,op) | (kwd,op,_) <- opcodes ]
-
-opNameTable :: Array GMLOp Name
-opNameTable = array (minBound,maxBound)
- [ (op,name) | (name,TOp op,_) <- opcodes ]
-
-undef = error "undefined function"
-image = error "undefined function: talk to image group"
-
--- typically, its best to have *one* opcode table,
--- so that mis-alignments do not happen.
-
-opcodes :: [(String,GMLToken,PrimOp)]
-opcodes =
- [ ("apply", TApply, error "incorrect use of apply")
- , ("if", TIf, error "incorrect use of if")
- , ("false", TBool False, error "incorrect use of false")
- , ("true", TBool True, error "incorrect use of true")
- ] ++ map (\ (a,b,c) -> (a,TOp b,c))
- -- These are just invocation, any coersions need to occur between here
- -- and before arriving at the application code (like deg -> rad).
- [ ("acos", Op_acos, Real_Real (rad2deg . acos))
- , ("addi", Op_addi, Int_Int_Int (+))
- , ("addf", Op_addf, Real_Real_Real (+))
- , ("asin", Op_asin, Real_Real (rad2deg . asin))
- , ("clampf", Op_clampf, Real_Real clampf)
- , ("cone", Op_cone, Surface_Obj cone)
- , ("cos", Op_cos, Real_Real (cos . deg2rad))
- , ("cube", Op_cube, Surface_Obj cube)
- , ("cylinder", Op_cylinder, Surface_Obj cylinder)
- , ("difference", Op_difference, Obj_Obj_Obj difference)
- , ("divi", Op_divi, Int_Int_Int (ourQuot))
- , ("divf", Op_divf, Real_Real_Real (/))
- , ("eqi", Op_eqi, Int_Int_Bool (==))
- , ("eqf", Op_eqf, Real_Real_Bool (==))
- , ("floor", Op_floor, Real_Int floor)
- , ("frac", Op_frac, Real_Real (snd . properFraction))
- , ("get", Op_get, Arr_Int_Value ixGet)
- , ("getx", Op_getx, Point_Real (\ x y z -> x))
- , ("gety", Op_gety, Point_Real (\ x y z -> y))
- , ("getz", Op_getz, Point_Real (\ x y z -> z))
- , ("intersect", Op_intersect, Obj_Obj_Obj intersect)
- , ("length", Op_length, Arr_Int (succ . snd . bounds))
- , ("lessi", Op_lessi, Int_Int_Bool (<))
- , ("lessf", Op_lessf, Real_Real_Bool (<))
- , ("light", Op_light, Point_Color_Light light)
- , ("modi", Op_modi, Int_Int_Int (ourRem))
- , ("muli", Op_muli, Int_Int_Int (*))
- , ("mulf", Op_mulf, Real_Real_Real (*))
- , ("negi", Op_negi, Int_Int negate)
- , ("negf", Op_negf, Real_Real negate)
- , ("plane", Op_plane, Surface_Obj plane)
- , ("point", Op_point, Real_Real_Real_Point VPoint)
- , ("pointlight", Op_pointlight, Point_Color_Light pointlight)
- , ("real", Op_real, Int_Real fromIntegral)
- , ("render", Op_render, Render $ render eye)
- , ("rotatex", Op_rotatex, Obj_Real_Obj (\ o d -> rotateX (deg2rad d) o))
- , ("rotatey", Op_rotatey, Obj_Real_Obj (\ o d -> rotateY (deg2rad d) o))
- , ("rotatez", Op_rotatez, Obj_Real_Obj (\ o d -> rotateZ (deg2rad d) o))
- , ("scale", Op_scale, Obj_Real_Real_Real_Obj (\ o x y z -> scale (x,y,z) o))
- , ("sin", Op_sin, Real_Real (sin . deg2rad))
- , ("sphere", Op_sphere, Surface_Obj sphere') -- see comment at end of file
- , ("spotlight", Op_spotlight, Point_Point_Color_Real_Real_Light mySpotlight)
- , ("sqrt", Op_sqrt, Real_Real ourSqrt)
- , ("subi", Op_subi, Int_Int_Int (-))
- , ("subf", Op_subf, Real_Real_Real (-))
- , ("trace", Op_trace, Value_String_Value mytrace)
- , ("translate", Op_translate, Obj_Real_Real_Real_Obj (\ o x y z -> translate (x,y,z) o))
- , ("union", Op_union, Obj_Obj_Obj union)
- , ("uscale", Op_uscale, Obj_Real_Obj (\ o r -> uscale r o))
- ]
-
--- This enumerate all possible ways of calling the fixed primitives
-
--- The datatype captures the type at the *interp* level,
--- the type of the functional is mirrored on this (using Haskell types).
-
-data PrimOp
-
- -- 1 argument
- = Int_Int (Int -> Int)
- | Real_Real (Double -> Double)
- | Point_Real (Double -> Double -> Double -> Double)
- | Surface_Obj (SurfaceFn Color Double -> Object)
- | Real_Int (Double -> Int)
- | Int_Real (Int -> Double)
- | Arr_Int (Array Int GMLValue -> Int)
-
- -- 2 arguments
- | Int_Int_Int (Int -> Int -> Int)
- | Int_Int_Bool (Int -> Int -> Bool)
- | Real_Real_Real (Double -> Double -> Double)
- | Real_Real_Bool (Double -> Double -> Bool)
- | Arr_Int_Value (Array Int GMLValue -> Int -> GMLValue)
-
- -- Many arguments, typically image mangling
-
- | Obj_Obj_Obj (Object -> Object -> Object)
- | Point_Color_Light (Coords -> Color -> Light)
- | Real_Real_Real_Point (Double -> Double -> Double -> GMLValue)
- | Obj_Real_Obj (Object -> Double -> Object)
- | Obj_Real_Real_Real_Obj (Object -> Double -> Double -> Double -> Object)
- | Value_String_Value (GMLValue -> String -> GMLValue)
-
- | Point_Point_Color_Real_Real_Light
- (Coords -> Coords -> Color -> Radian -> Radian -> Light)
- -- And finally render
- | Render (Color -> [Light] -> Object -> Int -> Double -> Int -> Int -> String -> IO ())
-
-data Type
- = TyBool
- | TyInt
- | TyReal
- | TyString
- | TyCode
- | TyArray
- | TyPoint
- | TyObject
- | TyLight
- | TyAlpha
- | TyAbsObj
- deriving (Eq,Ord,Ix,Bounded)
-
-typeTable =
- [ ( TyBool, "Bool")
- , ( TyInt, "Int")
- , ( TyReal, "Real")
- , ( TyString, "String")
- , ( TyCode, "Code")
- , ( TyArray, "Array")
- , ( TyPoint, "Point")
- , ( TyObject, "Object")
- , ( TyLight, "Light")
- , ( TyAlpha, "<anything>")
- , ( TyAbsObj, "<abs>")
- ]
-
-typeNames = array (minBound,maxBound) typeTable
-
-instance Show Type where
- showsPrec _ op = showString (typeNames ! op)
-
-getPrimOpType :: PrimOp -> [Type]
-getPrimOpType (Int_Int _) = [TyInt]
-getPrimOpType (Real_Real _) = [TyReal]
-getPrimOpType (Point_Real _) = [TyPoint]
-getPrimOpType (Surface_Obj _) = [TyCode]
-getPrimOpType (Real_Int _) = [TyReal]
-getPrimOpType (Int_Real _) = [TyInt]
-getPrimOpType (Arr_Int _) = [TyArray]
-getPrimOpType (Int_Int_Int _) = [TyInt,TyInt]
-getPrimOpType (Int_Int_Bool _) = [TyInt,TyInt]
-getPrimOpType (Real_Real_Real _) = [TyReal,TyReal]
-getPrimOpType (Real_Real_Bool _) = [TyReal,TyReal]
-getPrimOpType (Arr_Int_Value _) = [TyArray,TyInt]
-getPrimOpType (Obj_Obj_Obj _) = [TyObject,TyObject]
-getPrimOpType (Point_Color_Light _) = [TyPoint,TyPoint]
-getPrimOpType (Real_Real_Real_Point _) = [TyReal,TyReal,TyReal]
-getPrimOpType (Obj_Real_Obj _) = [TyObject,TyReal]
-getPrimOpType (Obj_Real_Real_Real_Obj _) = [TyObject,TyReal,TyReal,TyReal]
-getPrimOpType (Value_String_Value _) = [TyAlpha,TyString]
-getPrimOpType (Point_Point_Color_Real_Real_Light _)
- = [TyPoint,TyPoint,TyPoint,TyReal,TyReal]
-getPrimOpType (Render _) = [TyPoint,
- TyLight,
- TyObject,
- TyInt,
- TyReal,
- TyReal,
- TyReal,
- TyString]
-
-
--- Some primitives with better error message
-
-mytrace v s = trace (s ++" : "++ show v ++ "\n") v
-
-
-ixGet :: Array Int GMLValue -> Int -> GMLValue
-ixGet arr i
- | inRange (bounds arr) i = arr ! i
- | otherwise = error ("failed access with index value "
- ++ show i
- ++ " (should be between 0 and "
- ++ show (snd (bounds arr)) ++ ")")
-
-ourQuot :: Int -> Int -> Int
-ourQuot _ 0 = error "attempt to use divi to divide by 0"
-ourQuot a b = a `quot` b
-
-ourRem :: Int -> Int -> Int
-ourRem _ 0 = error "attempt to use remi to divide by 0"
-ourRem a b = a `rem` b
-
-ourSqrt :: Double -> Double
-ourSqrt n | n < 0 = error "attempt to use sqrt on a negative number"
- | otherwise = sqrt n
-
-
-mySpotlight p1 p2 col cutoff exp = spotlight p1 p2 col (deg2rad cutoff) exp
-
--- The problem specification gets the mapping for spheres backwards
--- (it maps the image from right to left).
--- We've fixed that in the raytracing library so that it goes from left
--- to right, but to keep the GML front compatible with the problem
--- statement, we reverse it here.
-
-sphere' :: SurfaceFn Color Double -> CSG (SurfaceFn Color Double)
-sphere' (SFun f) = sphere (SFun (\i u v -> f i (1 - u) v))
-sphere' s = sphere s