-
+ CB79FB7B406A1D59AB393E1ADE0CCFB11DEEBEF1398F69E3BF73B675616339F018DF6EC769C54F2C922F4EE2DAC0C0FF60F571A9793BD0EBBC8AE1BE348C0FEB
adalisp/src/lispm.adb
(0 . 0)(1 . 696)
1162 -- Lisp machine, procedures for memory manipulation (at least for the
1163 -- time being).
1164 with Ada.Text_IO;
1165
1166 package body LispM is
1167
1168 -- The initial environment requires a set of symbols and their
1169 -- bindings to builtin functions/keywords. Thus we hold these into a
1170 -- statically-allocated table and we let the Lisp run-time copy them
1171 -- in AMem at the beginning of the world.
1172
1173 -- Constant symbol name size: 10 characters should be enough for
1174 -- everyone.
1175 subtype BuiltinNameSize is Integer range 1..10;
1176 -- Symbol name-builtin association
1177 type BuiltinAssoc is record
1178 BiName : String(BuiltinNameSize);
1179 BiValue : BuiltinID;
1180 end record;
1181 -- Array of BuiltinAssoc objects
1182 type BuiltinAssocs is array (Natural range <>) of BuiltinAssoc;
1183
1184 BuiltinTable : constant BuiltinAssocs :=
1185 (0 => (BiName => "+ ", BiValue => AddB),
1186 1 => (BiName => "- ", BiValue => SubB),
1187 2 => (BiName => "* ", BiValue => MulB),
1188 3 => (BiName => "/ ", BiValue => DivB),
1189 4 => (BiName => "quote ", BiValue => QuoteB),
1190 5 => (BiName => "eval ", BiValue => EvalB),
1191 6 => (BiName => "if ", BiValue => IfB),
1192 7 => (BiName => "cons ", BiValue => ConsB),
1193 8 => (BiName => "car ", BiValue => CarB),
1194 9 => (BiName => "cdr ", BiValue => CdrB),
1195 10 => (BiName => "list ", BiValue => ListB),
1196 11 => (BiName => "apply ", BiValue => ApplyB),
1197 12 => (BiName => "define ", BiValue => DefineB),
1198 13 => (BiName => "set! ", BiValue => SetB),
1199 14 => (BiName => "= ", BiValue => EqnB),
1200 15 => (BiName => "eq? ", BiValue => EqB),
1201 16 => (BiName => "eqv? ", BiValue => EqvB),
1202 17 => (BiName => "pair? ", BiValue => PairPB),
1203 18 => (BiName => "boolean? ", BiValue => BooleanPB),
1204 19 => (BiName => "number? ", BiValue => NumberPB),
1205 20 => (BiName => "symbol? ", BiValue => SymbolPB),
1206 21 => (BiName => "null? ", BiValue => NullPB),
1207 22 => (BiName => "list? ", BiValue => ListPB),
1208 23 => (BiName => "and ", BiValue => AndB),
1209 24 => (BiName => "or ", BiValue => OrB),
1210 25 => (BiName => "not ", BiValue => NotB),
1211 26 => (BiName => "lambda ", BiValue => LambdaB),
1212 27 => (BiName => "let ", BiValue => LetB),
1213 28 => (BiName => "reverse ", BiValue => ReverseB),
1214 29 => (BiName => "append ", BiValue => AppendB));
1215
1216 -- Hack: used for maintaining a special "quote" symbol used by the
1217 -- parser.
1218 Quote_Name : constant String := "quote";
1219
1220 -- Shifting functions for MWord, used for low-level arithmetic.
1221 function Shift_Left
1222 (Value : MWord;
1223 Amount : Natural)
1224 return MWord;
1225 pragma Import(Intrinsic, Shift_Left);
1226
1227 function Shift_Right
1228 (Value : MWord;
1229 Amount : Natural)
1230 return MWord;
1231 pragma Import(Intrinsic, Shift_Right);
1232
1233 -- Getters.
1234
1235 -- Get the ID of a builtin cell
1236 function Get_Builtin(C : Cell) return BuiltinID is
1237 begin
1238 pragma Assert (C.T = Builtin, "Not a builtin cell!");
1239 -- Disclaimer: This list is hand-maintained, programmer must
1240 -- ensure that 'Get' and 'Set' sides match!
1241 return BuiltinTable(Integer(C.Data)).BiValue;
1242 end Get_Builtin;
1243
1244 -- Get the car of a cons cell
1245 function Get_Car(C : Cell) return MemPtr is
1246 begin
1247 pragma Assert (C.T = Cons or C.T = Closure,
1248 "Car: Not a cons cell!");
1249 return MemPtr(Shift_Right(C.Data, 32));
1250 end Get_Car;
1251
1252 -- Get the cdr of a cons cell
1253 function Get_Cdr(C : Cell) return MemPtr is
1254 begin
1255 pragma Assert (C.T = Cons or C.T = Closure,
1256 "Cdr: Not a cons cell!");
1257 return MemPtr(C.Data and 16#0000_0000_FFFF_FFFF#);
1258 end Get_Cdr;
1259
1260 -- Get the value of a bool cell
1261 function Get_Bool(C : Cell) return Boolean is
1262 begin
1263 pragma Assert (C.T = Bool, "Not a bool cell!");
1264 pragma Assert (C.Data = 0 or C.Data = 1,
1265 "Bool cell in undefined state!");
1266 if (C.Data = 0) then
1267 return False;
1268 else
1269 return True;
1270 end if;
1271 end Get_Bool;
1272
1273 -- Get the value of a fixnum cell
1274 function Get_Fixnum(C : Cell) return Long_Integer is
1275 Temp : Long_Integer;
1276 begin
1277 pragma Assert (C.T = Fixnum, "Not a fixnum cell!");
1278 if (C.Data and 16#8000_0000_0000_0000#) /= 0 then
1279 Temp := -(Long_Integer(not C.Data) + 1);
1280 else
1281 Temp := Long_Integer(C.Data);
1282 end if;
1283 return Temp;
1284 end Get_Fixnum;
1285
1286 -- Get the value of a char cell
1287 function Get_Char(C : Cell) return Character is
1288 begin
1289 pragma Assert (C.T = Char, "Not a char cell!");
1290 return Character'Val(C.Data);
1291 end Get_Char;
1292
1293 -- Get the string (list-of-chars) associated with a symbol cell
1294 function Get_Symbol(C : Cell) return MemPtr is
1295 begin
1296 pragma Assert (C.T = Symbol, "Not a symbol cell!");
1297 return MemPtr(C.Data);
1298 end Get_Symbol;
1299
1300 -- Get the code of a closure cell (in practice, the pair car)
1301 function Get_Closure_Code(C : Cell) return MemPtr is
1302 begin
1303 return Get_Car(C);
1304 end Get_Closure_Code;
1305
1306 -- Get the env of a closure cell (in practice, the pair cdr)
1307 function Get_Closure_Env(C : Cell) return MemPtr is
1308 begin
1309 return Get_Cdr(C);
1310 end Get_Closure_Env;
1311
1312 -- Setters.
1313
1314 -- Set the value of a builtin cell.
1315 procedure Set_Builtin(C : in out Cell; B : in BuiltinID) is
1316 Index : Integer := -1;
1317 begin
1318 pragma Assert (C.T = Builtin, "Not a builtin cell!");
1319 -- Lookup builtin in table
1320 for I in 0..(BuiltinTable'Length - 1) loop
1321 if BuiltinTable(I).BiValue = B then
1322 Index := I;
1323 exit;
1324 end if;
1325 end loop;
1326 pragma Assert (Index /= -1, "Builtin not found.");
1327
1328 C.Data := MWord(Index);
1329 end Set_Builtin;
1330
1331 -- Set the car of a cons cell.
1332 procedure Set_Car(C : in out Cell; Car : in MemPtr) is
1333 begin
1334 pragma Assert (C.T = Cons or C.T = Closure,
1335 "Not a cons cell!");
1336 C.Data := (C.Data and 16#0000_0000_FFFF_FFFF#)
1337 or Shift_Left(MWord(Car), 32);
1338 end Set_Car;
1339
1340 -- Set the cdr of a cons cell.
1341 procedure Set_Cdr(C : in out Cell; Cdr : in MemPtr) is
1342 begin
1343 pragma Assert (C.T = Cons or C.T = Closure,
1344 "Not a cons cell!");
1345 C.Data := (C.Data and 16#FFFF_FFFF_0000_0000#)
1346 or MWord(Cdr);
1347 end Set_Cdr;
1348
1349 -- Set the value of a bool cell.
1350 procedure Set_Bool(C : in out Cell; Value : in Boolean) is
1351 begin
1352 pragma Assert (C.T = Bool, "Not a bool cell!");
1353 if Value then
1354 C.Data := 1;
1355 else
1356 C.Data := 0;
1357 end if;
1358 end Set_Bool;
1359
1360 -- Set the value of a fixnum cell.
1361 procedure Set_Fixnum(C : in out Cell; Value : in Long_Integer) is
1362 begin
1363 pragma Assert (C.T = Fixnum, "Not a fixnum cell!");
1364 if Value < 0 then
1365 C.Data := not MWord(-Value) + 1;
1366 else
1367 C.Data := MWord(Value);
1368 end if;
1369 end Set_Fixnum;
1370
1371 -- Set the value of a char cell.
1372 procedure Set_Char(C : in out Cell; Value : in Character) is
1373 begin
1374 pragma Assert (C.T = Char, "Not a char cell!");
1375 C.Data := MWord(Character'Pos(Value));
1376 end Set_Char;
1377
1378 -- Set the name of a symbol cell.
1379 procedure Set_Symbol(C : in out Cell; Name : in MemPtr) is
1380 IsStr : Boolean := True;
1381 PList : MemPtr := Name;
1382 PCar : MemPtr;
1383 begin
1384 pragma Assert (C.T = Symbol, "Not a symbol cell!");
1385
1386 -- Sanity check! At this point, a string is a list-of-chars, so we
1387 -- need to check that the type of list elements matches.
1388 pragma Assert (PList /= 0, "Symbol name is empty string!");
1389 while PList /= 0 loop
1390 pragma Assert (AMem(PList).T = Cons, "Not a string cons cell!");
1391
1392 -- Get car cell and check its type
1393 PCar := Get_Car(AMem(PList));
1394 if (AMem(PCar).T /= Char) then
1395 IsStr := False;
1396 exit;
1397 end if;
1398
1399 -- Get cdr cell
1400 PList := Get_Cdr(AMem(PList));
1401 end loop;
1402 pragma Assert(IsStr, "Symbol not a string!");
1403
1404 C.Data := MWord(Name);
1405 end Set_Symbol;
1406
1407 -- Set the closure code (car)
1408 procedure Set_Closure_Code(C : in out Cell; Code : in MemPtr) is
1409 begin
1410 Set_Car(C, Code);
1411 end Set_Closure_Code;
1412
1413 -- Set the closure env (cdr)
1414 procedure Set_Closure_Env(C : in out Cell; Env : in MemPtr) is
1415 begin
1416 Set_Cdr(C, Env);
1417 end Set_Closure_Env;
1418
1419 -- Allocate new cell in Lisp machine memory.
1420 procedure Alloc_Cell(C : in Cell; P : out MemPtr) is
1421 begin
1422 -- For now we just increase the heap and add the new cell.
1423
1424 -- Increase heap size
1425 Heap_End := Heap_End + 1;
1426 -- Check that we're overwriting a free cell.
1427 pragma Assert (AMem(Heap_End).T = Free,
1428 "Alloc_Cell using a non-free cell.");
1429 -- Assign given cell value
1430 AMem(Heap_End) := C;
1431 -- Set P to point to new pointer
1432 P := Heap_End;
1433 end Alloc_Cell;
1434
1435 -- Allocate builtin cell.
1436 procedure Alloc_Builtin(B : BuiltinID; P : out MemPtr) is
1437 begin
1438 Alloc_Cell((T => Builtin, Data => 0), P);
1439 Set_Builtin(AMem(P), B);
1440 end Alloc_Builtin;
1441
1442 -- Allocate a cons cell.
1443 procedure Alloc_Cons(Car, Cdr : in MemPtr; P : out MemPtr) is
1444 begin
1445 Alloc_Cell((T => Cons, Data => 0), P);
1446 Set_Car(AMem(P), Car);
1447 Set_Cdr(AMem(P), Cdr);
1448 end Alloc_Cons;
1449
1450 -- Allocate a bool cell.
1451 procedure Alloc_Bool(Value : in Boolean; P : out MemPtr) is
1452 begin
1453 Alloc_Cell((T => Bool, Data => 0), P);
1454 Set_Bool(AMem(P), Value);
1455 end Alloc_Bool;
1456
1457 -- Allocate a fixnum cell.
1458 procedure Alloc_Fixnum(Value : in Long_Integer; P : out MemPtr) is
1459 begin
1460 Alloc_Cell((T => Fixnum, Data => 0), P);
1461 Set_Fixnum(AMem(P), Value);
1462 end Alloc_Fixnum;
1463
1464 -- Allocate a char cell.
1465 procedure Alloc_Char(Value : in Character; P : out MemPtr) is
1466 begin
1467 Alloc_Cell((T => Char, Data => 0), P);
1468 Set_Char(AMem(P), Value);
1469 end Alloc_Char;
1470
1471 -- Allocate a symbol cell.
1472 procedure Alloc_Symbol(Name : in MemPtr; P : out MemPtr) is
1473 begin
1474 Alloc_Cell((T => Symbol, Data => 0), P);
1475 Set_Symbol(AMem(P), Name);
1476 end Alloc_Symbol;
1477
1478 -- Allocate a closure cell.
1479 procedure Alloc_Closure(Code, Env : in MemPtr; P : out MemPtr) is
1480 begin
1481 Alloc_Cell((T => Closure, Data => 0), P);
1482 Set_Closure_Code(AMem(P), Code);
1483 Set_Closure_Env(AMem(P), Env);
1484 end Alloc_Closure;
1485
1486 -- Dump cell from Lisp machine memory.
1487 procedure Dump_Cell(P : in MemPtr) is
1488 use Ada.Text_IO;
1489
1490 C : Cell;
1491 begin
1492 -- Check for NIL.
1493 if (P = 0) then
1494 -- Scheme notation.
1495 Put("()");
1496 return;
1497 end if;
1498
1499 -- Otherwise our cell lies in AMem. It's either a free cell or it
1500 -- has some allocated data in it.
1501 C := AMem(P);
1502 case C.T is
1503 when Free =>
1504 Put("<free cell>");
1505 when Builtin =>
1506 -- XXX check whether the builtin is a function or a keyword.
1507 Put("<builtin func ");
1508 Dump_BuiltinID(Get_Builtin(C));
1509 Put(">");
1510 when Cons =>
1511 Dump_Cons(P);
1512 when Bool =>
1513 if C.Data = 0 then
1514 Put("#f");
1515 else
1516 Put("#t");
1517 end if;
1518 when Fixnum =>
1519 Dump_Longint(Get_Fixnum(C));
1520 when Char =>
1521 Put("#\");
1522 if Get_Char(C) = ' ' then
1523 Put("space");
1524 else
1525 Put(Get_Char(C));
1526 end if;
1527 when Symbol =>
1528 Dump_String(Get_Symbol(C));
1529 when Closure =>
1530 Put("<closure>");
1531 end case;
1532 end Dump_Cell;
1533
1534 -- Recursively dump a cons cell, doing sugary processing.
1535 procedure Dump_Cons(P : in MemPtr) is
1536 use Ada.Text_IO;
1537
1538 C : Cell;
1539 begin
1540 -- Initialization and sanity checks
1541 pragma Assert (P /= 0, "List must be non-empty.");
1542 C := AMem(P);
1543 pragma Assert (C.T = Cons,
1544 "Dump_Cons must receive pointer to a Cons cell.");
1545
1546 -- Special processing: if our cons is a list of the form (quote
1547 -- expr), print 'expr.
1548 declare
1549 CarP, CdrP, CadrP : MemPtr;
1550 begin
1551 CarP := Get_Car(C);
1552 CdrP := Get_Cdr(C);
1553 -- Car(P) = Quote_Sym?
1554 if CarP = Quote_Sym then
1555 -- Cdr(P) /= 0?
1556 if CdrP = 0 then
1557 Put("()");
1558 return;
1559 end if;
1560 -- Get Cadr(P)
1561 CadrP := Get_Car(AMem(CdrP));
1562 -- 'expr
1563 Put("'");
1564 Dump_Cell(CadrP);
1565 return;
1566 end if;
1567 end;
1568
1569 -- This cons cell may be a list, so we iterate through it as
1570 -- long as possible and recursively call ourselves.
1571 Put("(");
1572 Dump_Cell(Get_Car(C));
1573
1574 -- XXX This will fail *hard* for circular lists!
1575 while Get_Cdr(C) /= 0 loop
1576 -- Exit if cdr(C).tag /= cons.
1577 exit when (AMem(Get_Cdr(C)).T /= Cons);
1578 C := AMem(Get_Cdr(C));
1579
1580 Put(" ");
1581 Dump_Cell(Get_Car(C));
1582 end loop;
1583
1584 -- What remains should be either a NIL or some other
1585 -- value. In the latter case, print it in dotted format.
1586 if Get_Cdr(C) /= 0 then
1587 Put(" . ");
1588 Dump_Cell(Get_Cdr(C));
1589 end if;
1590 Put(")");
1591 end Dump_Cons;
1592
1593 procedure Dump_Longint(N : in Long_Integer) is
1594 use Ada.Text_IO;
1595
1596 N1, N2 : Long_Integer;
1597 Num_Digits : Integer;
1598 begin
1599 -- 0
1600 if N = 0 then
1601 Put("0");
1602 return;
1603 end if;
1604
1605 -- Check whether N is negative
1606 if N < 0 then
1607 Put('-');
1608 N1 := -N;
1609 else
1610 N1 := N;
1611 end if;
1612
1613 -- Compute the number of digits
1614 N2 := 0;
1615 Num_Digits := 0;
1616 while N1 /= 0 loop
1617 N2 := N2 * 10 + N1 rem 10;
1618 N1 := N1 / 10;
1619 Num_Digits := Num_Digits + 1;
1620 end loop;
1621 -- Same, but algorithm, but print digit by digit
1622 while Num_Digits > 0 loop
1623 N1 := N2 rem 10;
1624 N2 := N2 / 10;
1625 Put(Character'Val(N1 + Character'Pos('0')));
1626 Num_Digits := Num_Digits - 1;
1627 end loop;
1628 end Dump_Longint;
1629
1630 procedure Dump_BuiltinID(BID : in BuiltinID) is
1631 use Ada.Text_IO;
1632 begin
1633 case BID is
1634 when AddB => Put("+");
1635 when SubB => Put("-");
1636 when MulB => Put("*");
1637 when DivB => Put("/");
1638 when QuoteB => Put("quote");
1639 when EvalB => Put("eval");
1640 when IfB => Put("if");
1641 when ConsB => Put("cons");
1642 when CarB => Put("car");
1643 when CdrB => Put("cdr");
1644 when ListB => Put("list");
1645 when ApplyB => Put("apply");
1646 when DefineB => Put("define");
1647 when SetB => Put("set");
1648 when EqnB => Put("eqn");
1649 when EqB => Put("eq");
1650 when EqvB => Put("eqv");
1651 when PairPB => Put("pairp");
1652 when BooleanPB => Put("booleanp");
1653 when NumberPB => Put("numberp");
1654 when SymbolPB => Put("symbolp");
1655 when NullPB => Put("nullp");
1656 when ListPB => Put("listp");
1657 when AndB => Put("and");
1658 when OrB => Put("or");
1659 when NotB => Put("not");
1660 when LambdaB => Put("lambda");
1661 when LetB => Put("let");
1662 when ReverseB => Put("reverse");
1663 when AppendB => Put("append");
1664 end case;
1665 end Dump_BuiltinID;
1666
1667 -- Dump string represented as list of characters.
1668 procedure Dump_String(P : in MemPtr) is
1669 use Ada.Text_IO;
1670
1671 CarP, ListP : MemPtr;
1672 begin
1673 ListP := P;
1674 while ListP /= 0 loop
1675 pragma Assert(AMem(ListP).T = Cons, "Not a string-as-list!");
1676 CarP := Get_Car(AMem(ListP));
1677
1678 -- print elem.
1679 pragma Assert(AMem(CarP).T = Char, "Not a list of chars!");
1680 Put(Get_Char(AMem(CarP)));
1681
1682 -- next
1683 ListP := Get_Cdr(AMem(ListP));
1684 end loop;
1685 end Dump_String;
1686
1687 -- Init default bindings to builtin functions
1688 procedure Init_Builtin_Bindings is
1689 BuiltinP : MemPtr;
1690 SymP : MemPtr;
1691 CharP : MemPtr;
1692 NameP : MemPtr;
1693 begin
1694 -- Allocate symbol-value pair for each builtin, and add it to the
1695 -- front of Symbol_Table list.
1696 for I in 0..(BuiltinTable'Length - 1) loop
1697 -- allocate builtin
1698 Alloc_Builtin(BuiltinTable(I).BiValue, BuiltinP);
1699 -- allocate name
1700 NameP := 0;
1701 for K in reverse BuiltinTable(I).BiName'Range loop
1702 -- skip spaces
1703 if BuiltinTable(I).BiName(K) /= ' ' then
1704 Alloc_Char(BuiltinTable(I).BiName(K), CharP);
1705 Alloc_Cons(CharP, NameP, NameP);
1706 end if;
1707 end loop;
1708 pragma Assert(NameP /= 0, "Name is empty!");
1709 Alloc_Symbol(NameP, SymP); -- create symbol
1710 Alloc_Cons(SymP, Sym_Table, Sym_Table); -- intern
1711 Bind_Env(SymP, BuiltinP, Global_Env, SymP); -- bind in global namespace
1712 end loop;
1713
1714 -- XXX: Set Quote_Sym to be used by parser routine to convert the
1715 -- quote token to a proper S-expression. This is quite a
1716 -- hack, quote symbol could be represented as its own constant by
1717 -- lispm.
1718 NameP := 0;
1719 for K in reverse Quote_Name'Range loop
1720 Alloc_Char(Quote_Name(K), CharP);
1721 Alloc_Cons(CharP, NameP, NameP);
1722 end loop;
1723
1724 Lookup_Symbol(NameP, Quote_Sym);
1725
1726 -- Use these for debugging.
1727
1728 -- Dump_Cell(Sym_Table);
1729 -- Dump_Cell(Global_Env);
1730 end Init_Builtin_Bindings;
1731
1732 function Name_EqualP(Sym1, Sym2 : MemPtr) return Boolean is
1733 TempStr1, TempStr2 : MemPtr;
1734 P1, P2 : MemPtr;
1735 C1, C2 : Character;
1736 Same : Boolean := True;
1737 begin
1738 TempStr1 := Sym1;
1739 TempStr2 := Sym2;
1740 -- Compare strings character by character: iterate while any of
1741 -- the strings are not NIL.
1742 while TempStr1 /= 0 or TempStr2 /= 0 loop
1743 -- If any of them is NIL, then stop and return false.
1744 if TempStr1 = 0 or TempStr2 = 0 then
1745 Same := False;
1746 exit;
1747 end if;
1748 -- Otherwise, do the cars match?
1749 P1 := Get_Car(AMem(TempStr1)); C1 := Get_Char(AMem(P1));
1750 P2 := Get_Car(AMem(TempStr2)); C2 := Get_Char(AMem(P2));
1751 if C1 /= C2 then
1752 Same := False;
1753 exit;
1754 end if;
1755 -- If they do, check the rest.
1756 TempStr1 := Get_Cdr(AMem(TempStr1));
1757 TempStr2 := Get_Cdr(AMem(TempStr2));
1758 end loop;
1759
1760 return Same;
1761 end Name_EqualP;
1762
1763 -- Lookup Sym_Table for symbol whose name field is equal to Name.
1764 procedure Lookup_Symbol(Name : in MemPtr; Sym : out MemPtr) is
1765 ListP : MemPtr := Sym_Table;
1766 begin
1767 -- Assume we haven't found a value
1768 Sym := 0;
1769
1770 -- Iterate through Sym_Table
1771 while ListP /= 0 loop
1772 declare
1773 CurrSym : MemPtr := Get_Car(AMem(ListP));
1774 CurrName : MemPtr;
1775 begin
1776 pragma Assert(CurrSym /= 0, "Sym_Table contains a NIL symbol!");
1777 pragma Assert(AMem(CurrSym).T = Symbol,
1778 "Sym_Table contains a non-symbol!");
1779 -- Compare the given symbol name with the current alist value.
1780 CurrName := Get_Symbol(AMem(CurrSym));
1781 -- Found?
1782 if Name_EqualP(Name, CurrName) then
1783 Sym := CurrSym;
1784 exit;
1785 end if;
1786 -- Otherwise keep looking
1787 ListP := Get_Cdr(AMem(ListP));
1788 end;
1789 end loop;
1790 end Lookup_Symbol;
1791
1792 -- Lookup Name in Sym_Table; if non-existent, add a new (Name . NIL)
1793 -- pair to the table and set NameVal to it.
1794 procedure Lookup_Or_Create_Symbol(Name : in MemPtr; Sym: out MemPtr) is
1795 TempSym : MemPtr;
1796 begin
1797 -- Lookup for Name
1798 Lookup_Symbol(Name, TempSym);
1799 -- If not found, intern Name
1800 if TempSym = 0 then
1801 Alloc_Symbol(Name, TempSym);
1802 Alloc_Cons(TempSym, Sym_Table, Sym_Table);
1803 end if;
1804 -- Return symbol
1805 Sym := TempSym;
1806 end Lookup_Or_Create_Symbol;
1807
1808 -- Lookup Sym in Env set Binding to the Sym-Value pair if found.
1809 procedure Lookup_Env(Sym, Env : in MemPtr; Binding : out MemPtr) is
1810 EnvP : MemPtr := Env;
1811 begin
1812 -- NIL by default
1813 Binding := 0;
1814
1815 while EnvP /= 0 loop
1816 declare
1817 CurrBinding : MemPtr := Get_Car(AMem(EnvP));
1818 CurrSym : MemPtr;
1819 begin
1820 pragma Assert (CurrBinding /= 0, "NIL binding in Env!");
1821 -- Get symbol of current binding
1822 CurrSym := Get_Car(AMem(CurrBinding));
1823 pragma Assert(AMem(CurrSym).T = Symbol, "Not a symbol!");
1824 -- Compare symbols pointer-wise
1825 if Sym = CurrSym then
1826 Binding := CurrBinding;
1827 exit;
1828 end if;
1829 EnvP := Get_Cdr(AMem(EnvP));
1830 end;
1831 end loop;
1832 end Lookup_Env;
1833
1834 -- Lookup value of Sym in Env or Global_Env
1835 procedure Lookup_Env_Or_Global(Sym, Env : in MemPtr;
1836 Binding : out MemPtr) is
1837 TempP : MemPtr;
1838 begin
1839 Lookup_Env(Sym, Env, TempP);
1840 if TempP = 0 then
1841 Lookup_Env(Sym, Global_Env, Binding);
1842 else
1843 Binding := TempP;
1844 end if;
1845 end Lookup_Env_Or_Global;
1846
1847 -- Add Sym-Value binding in Env and set Binding to the new pair.
1848 procedure Bind_Env(Sym, Value : in MemPtr;
1849 Env : in out MemPtr; Binding : out MemPtr) is
1850 TempP : MemPtr;
1851 begin
1852 Alloc_Cons(Sym, Value, TempP); -- create pair
1853 Alloc_Cons(TempP, Env, Env); -- cons pair to env
1854
1855 Binding := TempP; -- return pair.
1856 end Bind_Env;
1857 end LispM;