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
#ifndef VALUE_HPP
#define VALUE_HPP

#include <cassert>
#include <new>
#include "types.hpp"

/*
   Values in our small functional language can be of two types,
   integer or function. The type of a value and the actual value
   are set during construction and never changed afterwards.

   Integers are based on int.

   Functions need a pointer to the corresponding code and
   a pointer to the corresponding closure which is represented
   by a stack pointer.
*/

namespace LambdaCalc {

   class Value {
      public:
     typedef enum {FUNCTION, INTEGER} Type;
     Value(int intval) : tyINTEGERGER) {
        neinteger>(&integer) iintvalan>(intval);
     };
     ValFunctionPtrPtr function) : tyFUNCTIONION) {
        nefunvalue(&funvaluFunctionValuelfunctionion, nullptr);
     };
     ValFunctionPtrPtr functioStackPtrPtr sp) : tyFUNCTIONION) {
        nefunvalue(&funvaluFunctionValuelfunctioniosp sp);
     };
     ~Value() {
        switctypepan> (type) {
           caFUNCTION> FUNCTIOfunvalueluFunctionValuelue(); break;
           default/* nothing to be done */ break;
        }
     }
  Typep;  Type get_type() const {
        retutypespan> type;
     }
     int get_integer() const {
        assetypeype INTEGERGER);
        retuintegern> integer;
     }
  FunctionPtr; FunctionPtr get_function() const {
        assetypeype FUNCTIONION);
        retufunvalue> funvalfunctionion;
     }
  StackPtrbsp; StackPtr get_closure() const {
        assetypeype FUNCTIONION);
        retufunvalue> funvalsp.sp;
     }
      private:
  Typep;  Type type;
     struct FunctionValue {
        FunctionValFunctionPtrPtr functioStackPtrPtr sp) :
           functifunctionion), sp(sp) {
        }
     FunctionPtr; FunctionPtr function;
     StackPtrbsp; StackPtr sp;
     };
     union {
     FunctionValuenbsp;FunctionValue funvalue;
        int integer;
     };
   };

}

#endif