-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathlisptypes.pas
151 lines (121 loc) · 2.67 KB
/
lisptypes.pas
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
{$ifdef Interface}
{ Base Types }
type
LV = class
public
function ToWrite: string; virtual;
function ToDisplay: string; virtual;
function Equals(X: LV): Boolean; virtual;
end;
TLispType = class of LV;
PLV = ^LV;
TLVArray = array[0..MaxInt div SizeOf(LV)] of LV;
PLVArray = ^TLVArray;
ELispError = class(Exception)
public
constructor Create(Msg: string; What: LV);
end;
{$include lispdata.pas}
{ Multiple Values }
type
TLispMultipleValues = class(LV)
private
FFirst, FRest: LV;
public
property First: LV read FFirst;
property Rest: LV read FRest;
function ToWrite: string; override;
function ToDisplay: string; override;
constructor Create(AFirst, ARest: LV);
end;
procedure LispTypeCheck(X: LV; Expected: TLispType; Msg: string);
function LispTypePredicate(T: TLispType): LV;
{$else}
{$include lispdata.pas}
procedure LispTypeCheck(X: LV; Expected: TLispType; Msg: string);
begin
if not (X is Expected) then
begin
raise ELispError.Create(Msg, X);
end;
end;
type
TLispTypePredicate = class
private
FType: TLispType;
public
function Check(Args: Pointer): LV;
constructor Create(T: TLispType);
end;
function TLispTypePredicate.Check(Args: Pointer): LV;
var
X: LV;
begin
LispParseArgs(Args, [@X]);
Result := LispBoolean(X is FType);
end;
constructor TLispTypePredicate.Create(T: TLispType);
begin
FType := T;
end;
function LispTypePredicate(T: TLispType): LV;
var
Tester: TLispTypePredicate;
begin
Tester := TLispTypePredicate.Create(T);
Result := LispPrimitive(Tester.Check);
end;
{ LV }
function LV.ToWrite: string;
begin
Result := '';
end;
function LV.ToDisplay: string;
begin
Result := ToWrite;
end;
function LV.Equals(X: LV): Boolean;
begin
Result := X = Self;
end;
{ ELispError }
constructor ELispError.Create(Msg: string; What: LV);
begin
if (What = nil) or (What = LispVoid) then
begin
inherited Create(Msg);
end
else
begin
inherited Create(Msg + ': ' + LispToWrite(What));
end;
end;
{ TLispMultipleValues }
const
LineFeed = #10;
function MultivalToString(X: TLispMultipleValues; Display: Boolean): string;
var
Cur: LV;
begin
Result := LispDataToString(X.First, Display);
Cur := X.Rest;
while Cur <> LispEmpty do
begin
Result := Result + LineFeed + LispDataToString(LispCar(Cur), Display);
Cur := LispCdr(Cur);
end;
end;
function TLispMultipleValues.ToWrite: string;
begin
Result := MultivalToString(Self, False);
end;
function TLispMultipleValues.ToDisplay: string;
begin
Result := MultivalToString(Self, True);
end;
constructor TLispMultipleValues.Create(AFirst, ARest: LV);
begin
FFirst := AFirst;
FRest := ARest;
end;
{$endif}