Plan 9 from Bell Labs’s /usr/web/sources/contrib/fernan/nhc98/tests/nofib/real/PolyGP/Eval.hs

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


{---------------------------------------------------------------
 --
 -- Eval.hs : contains function definition which evaluate/interpret
 --	      the genetic programs evolved by the system.
 -- T.Yu@cs.ucl.ac.uk	September 25, 1997
 --
 --------------------------------------------------------------}

module Eval (evalExp,atoi,atof) where
import Header(TypeExp(..), Expression(..))
import Local(runTimeErrorHandler)
import Char(ord)
import NonStdTrace



--evalExp function---------------------------------------------------------------
--
-- This function takes 3 arguments : an expression, an adf list and counter.
-- It evaluates the expression and return its result, an expression. The counter
-- is used to check for recursive calls.

evalExp:: Expression -> [(String,Expression)] -> Int -> Bool -> Bool -> Bool -> (Expression,Bool,Bool,Bool)

evalExp exp adfs counter rtError halt debug = 
  case exp of
    {
	(Constant x) -> (exp, rtError, halt,debug);
	(List x) -> (exp, rtError, halt,debug);
	(Variable x) -> (exp, rtError, halt,debug);
	(Primitive x) -> (exp, rtError, halt,debug);
	(Function x) -> (exp, rtError, halt ,debug);
	(Lambda x e) -> (exp, rtError, halt,debug);

	-- head,tail,null (strict)

	(Application (Primitive f) arg t) ->
	 --trace ("Primitive1 : "++ show f ++ show arg ) $ 
  		if (not halt) || debug then
			(errorHandler t, rtError, halt, debug)
		else
			doPrim1 f arg t adfs counter rtError True False;

	-- +,-,==,cons(non-strict)

	(Application (Application (Primitive f) arg1 t1) arg2 t2) ->
	--trace ("Primitive2 : "++ show f ++ show arg1 ++ show arg2) $ 
		if (not halt) || debug then
			(errorHandler t2, rtError, halt, debug)
		else
			doPrim2 f arg1 arg2 t2 adfs counter rtError True False;

	--if-then-else (1st arg strict)

	(Application (Application (Application (Primitive f) arg1 t1 ) arg2 t2 ) arg3 t3) ->
	--trace ("Primitive3 : "++ show f ++ show arg1 ++ show arg2 ++ show arg3) $ 
  		if (not halt) || debug then
			(errorHandler t3, rtError, halt, debug)
  		else
			doPrim3 f arg1 arg2 arg3 t3 adfs counter rtError True False;

	--applicative-order reduction

	(Application (Lambda x e) y t) ->
	--trace ("Lambda "++ show x ++ show e ++ show y) $ 
	if (not halt) || debug then
		(errorHandler t, rtError, halt, debug)
	else
		case (evalExp y adfs counter rtError True False) of 
		 { (y', rtError', halt',debug') -> 
			if (not halt') || debug' then
			  (errorHandler t,rtError',True, False)
		  	else
			  evalExp (betaReduction y' x e) adfs counter rtError' True False
		};

	--normal-order reduction (app (app (lambda f.lambda l e) aF) aL)

	(Application (Application (Lambda f e) aF t1) aL t2) ->
	--trace ("Lambda "++ show f ++ show e ++ show aF ++ show aL) $ 
	if (not halt) || debug then
		(errorHandler t2 ,rtError, halt, debug)
	else	
		case (evalExp aF adfs counter rtError True False) of
		{ (aF',rtError', halt',debug') ->
		  if (not halt') || debug' then
			(errorHandler t2, rtError', halt',debug')
		  else
			evalExp (Application (betaReduction aF' f e) aL t2) adfs counter rtError' True False
		};

	--make a copy of the adf expression

	(Application (Function x) e t) ->
	--trace ("Function "++ show x ++ show e ) $ 
	if (counter <= 0) || (not halt)  then 
		(errorHandler t,rtError, False, debug) -- map return type is ListType TypeVar T2
	else if debug then
		(errorHandler t,rtError, True, True) -- map return type is ListType TypeVar T2
	else
		evalExp (Application (lookUp x adfs) e t) adfs (counter-1) rtError True False;

	--make a copy of the adf expression

	(Application (Application (Function x) e1 t1) e2 t2) ->
	--trace ("Function "++ show x ++ show e1 ++ show e2) $ 
	if (counter <= 0) || not halt then 
		(errorHandler t2, rtError, False, debug) -- map return type is ListType TypeVar T2
	else if debug then
		(errorHandler t2, rtError, True, True)
	else
		evalExp (Application (Application (lookUp x adfs) e1 t1) e2 t2) adfs (counter-1) rtError True False;

	(Application f e t) ->  -- ** a DEBUGGING statement--
		trace ("evalExp:  "++ show exp ) $
		(errorHandler t, rtError, halt, True)
	}

--doPrim1 function--------------------------------------------------------------------------------------------
--
-- This function takes 6 arguments : name of the primitive function, expression to be evaluated ,
-- return type of the expression, adf list, counter and rtError flag.
-- It evaluates the expression and returns the result.
-- Note: only when the rtError is False that is function can be envoked. evalExp checks this.

doPrim1 :: String -> Expression -> TypeExp -> [(String, Expression)] -> Int -> Bool -> Bool -> Bool -> (Expression,Bool,Bool,Bool)

doPrim1 funName exp aType adfs counter rtError halt debug = 
	case funName of
	{
	  "head" ->
		--trace ("doPrim1 head :"++show exp) $
		case (evalExp exp adfs counter rtError halt debug) of
		{ (List aList, rtError', halt',debug') ->
	   	  if (not halt') || debug' then
			(errorHandler aType, rtError', halt', debug')
	   	  else
			if null aList then -- head of [] is a run-time error
		  	(errorHandler aType, True, True, False)
	   		else 
		  	evalExp (head aList) adfs counter rtError' True False;
		  (exp', rtError', halt', debug') -> -- ** a DEBUGGING statement--
			trace ("head:  "++ show exp ) $
			(errorHandler aType, rtError', halt', True)
		};

	  "tail" ->
		--trace ("doPrim1 tail :"++show exp) $
		case (evalExp exp adfs counter rtError halt debug) of
		{ (List aList,rtError', halt',debug') ->
	   	  if (not halt') || debug' then
			(errorHandler aType, rtError', halt', debug')
	   	  else
			if null aList then 
		   		(List [],True,True, False)  -- tail of [] is []. ?? wrong ??
			else 
		   		evalExp (List (tail aList)) adfs counter rtError' True False;
		  (exp', rtError', halt', debug') -> -- ** a DEBUGGING statement--
			trace ("tail:  "++ show exp ) $
			(errorHandler aType, rtError', halt', True)	
		};

	"null" ->
		--trace ("doPrim1 null :"++show exp) $
		case (evalExp exp adfs counter rtError halt debug) of
		{ (List aList,rtError', halt',debug') ->
	  	  if (not halt') || debug' then
			(Constant "false",rtError', halt', debug')
		  else
		  	if (null aList) then 
				(Constant "true",rtError',True, False)
	  	  	else (Constant "false",rtError', True,False);
		  (exp', rtError', halt', debug') -> -- ** a DEBUGGING statement--
			trace ("null:  "++ show exp ) $
			(errorHandler aType, rtError', halt', True)
		};

	"length" ->
		--trace ("doPrim1 length :"++show exp) $
		case (evalExp exp adfs counter rtError halt debug) of
		{ (List aList,rtError', halt',debug') ->
	  	  if (not halt') || debug' then
			(Constant "0",rtError', halt', debug')
		  else
	  	  	(Constant (show (length aList)),rtError', True,False);

		  (exp', rtError', halt', debug') -> -- ** a DEBUGGING statement--
			trace ("length:  "++ show exp ) $
			(errorHandler aType, rtError', halt', True)
		};

	"aton" ->
		--trace ("doPrim1 aton :"++show exp) $
		case (evalExp exp adfs counter rtError halt debug) of
		{ (Constant alphabet,rtError', halt',debug') ->
	  	  if (not halt') || debug' then
			(Constant "0",rtError', halt', debug')
		  else
	  	  	(Constant (show ((ord (head alphabet))-64)) ,rtError', True,False);

		  (exp', rtError', halt', debug') -> -- ** a DEBUGGING statement--
			trace ("aton:  "++ show exp ) $
			(errorHandler aType, rtError', halt', True)
		};

	_ ->  -- ** a DEBUGGING statement--
  	trace ("doPrim1:  "++ show funName ++ show exp) $
	(errorHandler aType, rtError, halt, True)
	}

-- doPrim2 function ---------------------------------------------------------------------------
-- This is the doPrim2 function

doPrim2 :: String -> Expression -> Expression -> TypeExp -> [(String,Expression)] -> Int -> Bool -> Bool -> Bool -> (Expression, Bool,Bool,Bool)

doPrim2 funName e1 e2 t adfs counter rtError halt debug = 
  case funName of
  {
	"+" ->
	--trace ("doPrim2 + :"++show e1 ++ show e2) $
	let (Constant a,rtError',halt',debug') = evalExp e1 adfs counter rtError halt debug
	    (Constant b,rtError'', halt'',debug'') = evalExp e2 adfs counter rtError' halt' debug'
	in
	    if (not halt'') || debug'' then
		(Constant "0", rtError'', halt'', debug'')
	    else
	    	(Constant (show ( (atoi a)+ (atoi b))), rtError'', True, False);

	"-" ->
	--trace ("doPrim2 - :"++show e1 ++ show e2) $
	let (Constant a, rtError', halt',debug') = evalExp e1 adfs counter rtError halt debug
	    (Constant b, rtError'', halt'',debug'') = evalExp e2 adfs counter rtError' halt' debug'
	in
	    if (not halt'') || debug'' then
		(Constant "0", rtError'', halt'', debug'')
	    else
	    	(Constant (show ((atoi a)- (atoi b))),rtError'', True, False);
	"*" ->
	--trace ("doPrim2 + :"++show e1 ++ show e2) $
	let (Constant a,rtError',halt',debug') = evalExp e1 adfs counter rtError halt debug
	    (Constant b,rtError'', halt'',debug'') = evalExp e2 adfs counter rtError' halt' debug'
	in
	    if (not halt'') || debug'' then
		(Constant "0", rtError'', halt'', debug'')
	    else
	    	(Constant (show ( (atoi a) * (atoi b))), rtError'', True, False);

	"==" ->
	--trace ("doPrim2 == :"++show e1 ++ show e2) $
	let (e1', rtError',halt',debug') = evalExp e1 adfs counter rtError halt debug
	    (e2', rtError'', halt'',debug'') = evalExp e2 adfs counter rtError' halt' debug'
	in
	    if (not halt'') || debug'' then
		(Constant "false", rtError'', halt'', debug'')
	    else
	    case (e1',e2') of
	    {
	    (Constant a, Constant b) ->
		if ((atoi a) == (atoi b)) == True then
			(Constant "true", rtError'', True, False)
 	    	else
	    		(Constant "false", rtError'', True, False);
	     _ -> trace ("== : " ++ show e1 ++ show e1' ++ show e2 ++show e2') $
		  error ("==  error \n")
	    };

	"<=" ->
	--trace ("doPrim2 <= :"++show e1 ++ show e2) $
	let (e1', rtError',halt',debug') = evalExp e1 adfs counter rtError halt debug
	    (e2', rtError'', halt'',debug'') = evalExp e2 adfs counter rtError' halt' debug'
	in
	    if (not halt'') || debug'' then
		(Constant "false", rtError'', halt'', debug'')
	    else
	    case (e1',e2') of
	    {
	    (Constant a, Constant b) ->
		if ((atoi a) <= (atoi b)) == True then
			(Constant "true", rtError'', True, False)
 	    	else
	    		(Constant "false", rtError'', True, False);
	     _ -> trace ("<= : " ++ show e1 ++ show e1' ++ show e2 ++show e2') $
		  error ("<=  error \n")
	    };

	">" ->
	--trace ("doPrim2 > :"++show e1 ++ show e2) $
	let (e1', rtError',halt',debug') = evalExp e1 adfs counter rtError halt debug
	    (e2', rtError'', halt'',debug'') = evalExp e2 adfs counter rtError' halt' debug'
	in
	    if (not halt'') || debug'' then
		(Constant "false", rtError'', halt'', debug'')
	    else
	    case (e1',e2') of
	    {
	    (Constant a, Constant b) ->
		if ((atoi a) > (atoi b)) == True then
			(Constant "true", rtError'', True, False)
 	    	else
	    		(Constant "false", rtError'', True, False);
	     _ -> trace ("> : " ++ show e1 ++ show e1' ++ show e2 ++show e2') $
		  error (">  error \n")
	    };

	--both x and exp are strict
	"cons" ->
	--trace ("doPrim2 cons:"++ show e1 ++ show e2) $
	case (evalExp e1 adfs counter rtError halt debug) of
	{ (e1',rtError', halt',debug') ->
	   if (not halt') || debug' then
		(List [],rtError', halt', debug')
	   else
		case (evalExp e2 adfs counter rtError' True False) of
 		{ (List e2',rtError'',halt'',debug'') ->
		   if (not halt'') || debug'' then
			(List [], rtError'', halt'', debug'')
		   else
			(List (e1':e2'), rtError'', True, False);
		  (e2', rtError'', halt'', debug'') -> -- ** a DEBUGGING statement--
		  	trace ("cons:  "++ show e1++show e2) $
			(errorHandler t , rtError'', halt'', True)
		}
	};

	_ -> -- ** a DEBUGGING statement--
	trace ("doPrim2: "++ show funName ++ show e1 ++ show e2) $
	(errorHandler t , rtError, halt, True)
	}
	
-- atoi function --------------------------------------------------------------------------------
--
atoi :: String -> Int
atoi ('-':s) = value - value*2
		where value = atoi s
atoi s = foldl g 0 s
	 where 
	 g x y = (10 * x) + ((ord y) - 48)

-- atof function ------------------------------------------------------------------
--

atof :: String -> Double
atof s = let (intPart,decimalPart) = break (=='.') s
	 in fromInteger (toInteger (atoi intPart)) + 
		fromInteger (toInteger (atoi (tail decimalPart))) / 
		10.00 ^ fromInteger (toInteger (length decimalPart - 1))

-- doPrim3 function ---------------------------------------------------------------------------
--

doPrim3 :: String -> Expression -> Expression -> Expression -> TypeExp -> [(String,Expression)] -> Int -> Bool -> Bool -> Bool -> (Expression,Bool,Bool,Bool)

doPrim3 funName test e1 e2 t adfs counter rtError halt debug = 
   case funName of
     {
	"if-then-else" ->
	--trace ("doPrim3 if-then-else :"++ show test ++show e1 ++ show e2) $
	case (evalExp test adfs counter rtError halt debug) of
	{ (result,rtError',halt', debug') ->
	  if (not halt') || debug' then
		(errorHandler t, rtError', halt', debug')
	   else
		if result == (Constant "true") then
			evalExp e1 adfs counter rtError' True False
		else if result == (Constant "false") then
			evalExp e2 adfs counter rtError' True False
		else -- ** a DEBUGGING statement--
  			trace ("if-then-else:  "++ show test ++show result) $
			(errorHandler t, rtError', halt', True)			
	};

	_ ->  -- ** a DEBUGGING statement--
  	trace ("doPrim3:  "++ show funName ++ show test++show e1++show e2) $
	(errorHandler t, rtError, halt, True)
     }

-- betaReduction funcation ----------------------------------------------------------------------------
-- replace y with x in e
--
betaReduction :: Expression -> String ->  Expression -> Expression

betaReduction y x exp = 
  case exp of
    {
	(Constant v) -> exp;
	(Primitive v) -> exp;
	(Function v) -> exp;
	(List v) -> exp;
	(Variable v) -> if v == x then --trace ("betaReduction: "++show v++show y++show x) $ 
				y 
	       		else Variable v;
	(Application e1 e2 t) -> (Application (betaReduction y x e1)(betaReduction y x e2) t);
	(Lambda a e) ->	(Lambda a (betaReduction y x e))
     }

-- need to deal with free variable, so far we use
-- different lambda-bound variable name to 
-- avoid the problem

-- lookUp function ---------------------------------------------------------------------------
--
-- This function takes 2 arguments: the name of the adf and the list of adfs.
-- It returns the adf (an expression) in the list whose name matches the given
-- name.

lookUp :: String -> [(String, Expression)] -> Expression

lookUp x table = case table of
		{
		 [] -> error "bad reference to ADF";
		 ((y,pt):rest) -> if  (x == y) then pt
				  else lookUp x rest 
		}

--errorHandler function -------------------------------------------------------------------
--
--
errorHandler :: TypeExp -> Expression

errorHandler t = errorHandlerAux t runTimeErrorHandler

errorHandlerAux :: TypeExp -> [(TypeExp, Expression)] -> Expression 

errorHandlerAux aType handlers = 
	case (aType, handlers ) of
	{
	(ListType x, (ListType _, exp):rest) -> exp ;
	(Brackets x, (Brackets _, exp):rest) -> exp ;
	(TypeVar x, (TypeVar _, exp):rest) -> exp ;
	(GenType x, (TypeVar _, exp):rest) -> exp ;
	(aType, (typeExp, exp):rest) ->	if aType == typeExp then exp 
		else errorHandlerAux aType rest ;
	(aType, []) -> trace ("errorHandler : " ++ show aType) $
			--   error "errorHandler"
			(List [])
	}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.