perl: Remove step 0.5.
[jackhill/mal.git] / objpascal / mal_env.pas
CommitLineData
0067158f
JM
1unit mal_env;
2
3{$H+} // Use AnsiString
4
5interface
6
7Uses sysutils,
8 fgl,
9 mal_types;
10
11type TEnv = class(TObject)
12 public
13 Data : TMalDict;
14 Outer : TEnv;
15
16 constructor Create;
17 constructor Create(_Outer : TEnv);
18 constructor Create(_Outer : TEnv;
19 Binds : TMalList;
20 Exprs : TMalArray);
21
22 function Add(Key : TMalSymbol; Val : TMal) : TMal;
23 function Find(Key : TMalSymbol) : TEnv;
24 function Get(Key : TMalSymbol) : TMal;
25end;
26
27////////////////////////////////////////////////////////////
28
29implementation
30
31constructor TEnv.Create();
32begin
33 inherited Create();
34 Self.Data := TMalDict.Create;
35 Self.Outer := nil;
36end;
37
38constructor TEnv.Create(_Outer: TEnv);
39begin
40 Self.Create();
41 Self.Outer := _Outer;
42end;
43
44constructor TEnv.Create(_Outer : TEnv;
45 Binds : TMalList;
46 Exprs : TMalArray);
47var
48 I : longint;
49 Bind : TMalSymbol;
50 Rest : TMalList;
51begin
52 Self.Create(_Outer);
53 for I := 0 to Length(Binds.Val)-1 do
54 begin
55 Bind := (Binds.Val[I] as TMalSymbol);
56 if Bind.Val = '&' then
57 begin
58 if I < Length(Exprs) then
59 Rest := TMalList.Create(copy(Exprs, I, Length(Exprs)-I))
60 else
61 Rest := TMalList.Create;
62 Self.Data[(Binds.Val[I+1] as TMalSymbol).Val] := Rest;
63 break;
64 end;
65 Self.Data[Bind.Val] := Exprs[I];
66 end;
67end;
68
69function TEnv.Add(Key : TMalSymbol; Val : TMal) : TMal;
70begin
71 Self.Data[Key.Val] := Val;
72 Add := Val;
73end;
74
75function TEnv.Find(Key : TMalSymbol) : TEnv;
76var
77 Sym : string;
78begin
79 Sym := (Key as TMalSymbol).Val;
80 if Data.IndexOf(Sym) >= 0 then
81 Find := Self
82 else if Outer <> nil then
83 Find := Outer.Find(Key)
84 else
85 Find := nil;
86end;
87
88function TEnv.Get(Key : TMalSymbol) : TMal;
89var
90 Sym : string;
91 Env : TEnv;
92begin
93 Sym := (Key as TMalSymbol).Val;
94 Env := Self.Find(Key);
95 if Env <> nil then
96 Get := Env.Data[Sym]
97 else
98 raise Exception.Create('''' + Sym + ''' not found');
99end;
100
101end.