mirror of
https://github.com/kanaka/mal.git
synced 2024-11-10 12:47:45 +03:00
0067158f6d
- Move vector related step4 and step6 tests to optional. - Fix two step9 tests that weren't checking return value.
102 lines
2.1 KiB
ObjectPascal
102 lines
2.1 KiB
ObjectPascal
unit mal_env;
|
|
|
|
{$H+} // Use AnsiString
|
|
|
|
interface
|
|
|
|
Uses sysutils,
|
|
fgl,
|
|
mal_types;
|
|
|
|
type TEnv = class(TObject)
|
|
public
|
|
Data : TMalDict;
|
|
Outer : TEnv;
|
|
|
|
constructor Create;
|
|
constructor Create(_Outer : TEnv);
|
|
constructor Create(_Outer : TEnv;
|
|
Binds : TMalList;
|
|
Exprs : TMalArray);
|
|
|
|
function Add(Key : TMalSymbol; Val : TMal) : TMal;
|
|
function Find(Key : TMalSymbol) : TEnv;
|
|
function Get(Key : TMalSymbol) : TMal;
|
|
end;
|
|
|
|
////////////////////////////////////////////////////////////
|
|
|
|
implementation
|
|
|
|
constructor TEnv.Create();
|
|
begin
|
|
inherited Create();
|
|
Self.Data := TMalDict.Create;
|
|
Self.Outer := nil;
|
|
end;
|
|
|
|
constructor TEnv.Create(_Outer: TEnv);
|
|
begin
|
|
Self.Create();
|
|
Self.Outer := _Outer;
|
|
end;
|
|
|
|
constructor TEnv.Create(_Outer : TEnv;
|
|
Binds : TMalList;
|
|
Exprs : TMalArray);
|
|
var
|
|
I : longint;
|
|
Bind : TMalSymbol;
|
|
Rest : TMalList;
|
|
begin
|
|
Self.Create(_Outer);
|
|
for I := 0 to Length(Binds.Val)-1 do
|
|
begin
|
|
Bind := (Binds.Val[I] as TMalSymbol);
|
|
if Bind.Val = '&' then
|
|
begin
|
|
if I < Length(Exprs) then
|
|
Rest := TMalList.Create(copy(Exprs, I, Length(Exprs)-I))
|
|
else
|
|
Rest := TMalList.Create;
|
|
Self.Data[(Binds.Val[I+1] as TMalSymbol).Val] := Rest;
|
|
break;
|
|
end;
|
|
Self.Data[Bind.Val] := Exprs[I];
|
|
end;
|
|
end;
|
|
|
|
function TEnv.Add(Key : TMalSymbol; Val : TMal) : TMal;
|
|
begin
|
|
Self.Data[Key.Val] := Val;
|
|
Add := Val;
|
|
end;
|
|
|
|
function TEnv.Find(Key : TMalSymbol) : TEnv;
|
|
var
|
|
Sym : string;
|
|
begin
|
|
Sym := (Key as TMalSymbol).Val;
|
|
if Data.IndexOf(Sym) >= 0 then
|
|
Find := Self
|
|
else if Outer <> nil then
|
|
Find := Outer.Find(Key)
|
|
else
|
|
Find := nil;
|
|
end;
|
|
|
|
function TEnv.Get(Key : TMalSymbol) : TMal;
|
|
var
|
|
Sym : string;
|
|
Env : TEnv;
|
|
begin
|
|
Sym := (Key as TMalSymbol).Val;
|
|
Env := Self.Find(Key);
|
|
if Env <> nil then
|
|
Get := Env.Data[Sym]
|
|
else
|
|
raise Exception.Create('''' + Sym + ''' not found');
|
|
end;
|
|
|
|
end.
|