summaryrefslogtreecommitdiff
path: root/graphics/asymptote/record.h
blob: 323a3d5878b00ebb1d7b3bbb1bc3f7255cf152be (plain)
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*****
 * record.h
 * Andy Hammerlindl 2003/07/09
 *
 * The type for records and modules in the language.
 *****/

#ifndef RECORD_H
#define RECORD_H

#include "types.h"
#include "env.h"
#include "frame.h"
#include "access.h"

namespace vm {
struct lambda;
}

using trans::frame;
using trans::protoenv;
using trans::varEntry;
using trans::tyEntry;

namespace types {

class record : public ty {
  // The base name of this type.
  symbol name;

  // The frame.  Like a frame for a function, it allocates the accesses
  // for fields and specifies the size of the record.
  frame *level;

  // The runtime representation of the record used by the virtual machine.
  vm::lambda *init;

public:
  // The name bindings for fields of the record.
  protoenv e;

  // These are name bindings that should be added to the enclosing environment
  // after translation of the record is completed.  Constructors implicitly
  // defined by "operator init" are stored here.
  protoenv postdefenv;

  record(symbol name, frame *level);
  ~record();

  symbol getName()
  {
    return name;
  }

  bool isReference() {
    return true;
  }

  size_t hash() const {
    // Use the pointer, as two records are equivalent only if they are the
    // same object.
    return (size_t)this;
  }

  // Initialize to null by default.
  trans::access *initializer();

  frame *getLevel(bool statically = false)
  {
    if (statically) {
      frame *f=level->getParent();
      return f ? f : level;
    }
    else
      return level;
  }

  vm::lambda *getInit()
  {
    return init;
  }

  // Allocates a new dynamic field in the record.
  trans::access *allocField(bool statically)
  {
    frame *underlevel = getLevel(statically);
    assert(underlevel);
    return underlevel->allocLocal();
  }

  // Create a statically enclosed record from this record.
  record *newRecord(symbol id, bool statically);

  void print(ostream& out) const
  {
    out << name;
  }

  void debug(ostream& out) const
  {
    out << "struct " << name << endl;
    out << "types:" << endl;
    out << "re-implement" << endl;
    //out << te;
    out << "fields: " << endl;
    out << "re-implement" << endl;
    //out << ve;
  }
};

// A record that is being used just for its fields and types, and has no real
// initializer.  This is for modules such as settings that are built into the
// language.
class dummyRecord : public record {
public:
  dummyRecord(symbol name);
  dummyRecord(string s);

  // Convenient functions for adding fields.
  void add(string name, ty *t, trans::access *a,
           trans::permission perm=trans::PUBLIC);
  void add(string name, function *t, vm::bltin f,
           trans::permission perm=trans::PUBLIC);
};

} //namespace types

#endif