packages feed

language-Modula2-0.1: examples/Dipl/NAMES.MOD

IMPLEMENTATION MODULE Names;

FROM SYSTEM IMPORT TSIZE;
FROM Lib IMPORT AddAddr, SubAddr, HashString;
FROM IO IMPORT WrStrAdj, WrLn;
FROM Str IMPORT Caps;
FROM Memory IMPORT ALLOCATE, MarkNeeded, AddMarker, DropMarker;
FROM Machine IMPORT link, closure, parent, tempDef;
FROM Machine IMPORT EmptyClosure, MarkClosure, MarkString;
FROM Machine IMPORT wType, Build, HandlePackage, HandleParent, SaveDefinition;
FROM Machine IMPORT AddEnv, RemoveEnv, MakeDef, MakePrimitive, MakeString;
CONST
	FormalMaximum=10000;
	MaxEntries=64;
	LastEntry=MaxEntries-1;
TYPE
	wordPtr=POINTER TO wordType;
	wordType=RECORD
					next:wordPtr;
					def:closure;
					name:POINTER TO ARRAY [0..FormalMaximum] OF CHAR;
					entry:closure;
				END;
	dictionary=POINTER TO dictRec;
	dictRec= RECORD
					info:ARRAY [0..LastEntry] OF wordPtr;
					next:dictionary
				 END;
VAR
	i:CARDINAL;
	top:dictionary;
	UndefinedMeaning:closure;
	
PROCEDURE DefWord(l:link):wordPtr;
BEGIN
	RETURN wordPtr(SubAddr(l,TSIZE(wordPtr)))
END DefWord;

PROCEDURE vList;
CONST
	WordsInRow=3;
	MaxLength=25;
VAR
	follow:wordPtr;
	i,counter:CARDINAL;
BEGIN
	counter:=1;
	FOR i:=0 TO LastEntry DO
		follow:=top^.info[i];
		WHILE follow#NIL DO
			DEC(counter);
			IF counter=0 THEN
				counter:=WordsInRow;
				WrLn
			END;
			WrStrAdj(follow^.name^,-MaxLength);
			follow:=follow^.next
		END
	END;
	WrLn
END vList;

PROCEDURE NewDictionary;
VAR
	d:dictionary;
	i:CARDINAL;
BEGIN
	NEW(d);
	FOR i:=0 TO LastEntry DO
		d^.info[i]:=top^.info[i]
	END;
	d^.next:=top;
	top:=d
END NewDictionary;

PROCEDURE OldDictionary;
BEGIN
	top:=top^.next
END OldDictionary;

PROCEDURE DefineWord(VAR worDef:link; wordName:ARRAY OF CHAR;
								wordMeaning:closure);
VAR
	newWord:wordPtr;
	hash:CARDINAL;
BEGIN
	hash:=HashString(wordName,MaxEntries);
	NEW(newWord);
	WITH newWord^ DO
		next:=top^.info[hash];
		top^.info[hash]:=newWord;
		name:=ADR(wordName);
		def:=EmptyClosure;
		entry:=EmptyClosure;
		worDef:=ADR(def);
		MakeDef(entry,wEntry);
		MakeDef(def,worDef);
		AddEnv(entry,wMeaning,def);
		MakeString(def,wString,name);
		AddEnv(entry,wName,def);
		def:=wordMeaning
	END
END DefineWord;

(*
PROCEDURE UndefineWord(l:link);
VAR
	hash:CARDINAL;
BEGIN
	hash:=HashString(DefWord(l)^.name^,MaxEntries);
	top^.info[hash]:=top^.info[hash]^.next
END UndefineWord;

PROCEDURE MoveWord(l:link; fromVoc, toVoc:dictionary);
VAR
	hash:CARDINAL;
	follow:POINTER TO wordPtr;
	wd:wordPtr;
BEGIN
	wd:=DefWord(l);
	hash:=HashString(wd^.name^,MaxEntries);
	IF fromVoc#EmptyDict THEN
		follow:=ADR(fromVoc^.info[hash]);
		WHILE (follow^#wd) AND (follow^#NIL) DO
			follow:=ADR(follow^^.next)
		END;
		IF follow^=wd THEN
			follow^:=follow^^.next
		END
	END;
	wd^.next:=toVoc^.info[hash];
	toVoc^.info[hash]:=wd
END MoveWord;

PROCEDURE Forget(dp:link):BOOLEAN;
VAR
	follow,target:wordPtr;
BEGIN
	target:=wordPtr(dp);
	follow:=lastWord;
	WHILE (follow#NIL) AND (follow#target) DO
		follow:=follow^.next
	END;
	IF follow=NIL THEN
		RETURN FALSE
	ELSE
		lastWord:=follow^.next;
		RETURN TRUE
	END
END Forget;
*)

PROCEDURE AddPrimWord(VAR worDef:link; wordName:ARRAY OF CHAR;
								handler:handlerType);
BEGIN
	MakePrimitive(tempDef,handler);
	DefineWord(worDef,wordName,tempDef);
	tempDef:=EmptyClosure
END AddPrimWord;

PROCEDURE AddArgument(VAR worDef:link; wordName:ARRAY OF CHAR);
BEGIN
	DefineWord(worDef,wordName,UndefinedMeaning)
END AddArgument;

PROCEDURE AddAtom(VAR worDef:link; wordName:ARRAY OF CHAR);
BEGIN
	AddPrimWord(worDef,wordName,Build);
	MakeDef(tempDef,worDef);
	AddEnv(worDef^,wType,tempDef);
	tempDef:=EmptyClosure
END AddAtom;
	
PROCEDURE MarkWords;
VAR
	i:[0..LastEntry];
	wdCurrent:wordPtr;
	dictFollow:dictionary;
	fresh:BOOLEAN;
BEGIN
	MarkClosure(UndefinedMeaning);
	dictFollow:=top;
	WHILE dictFollow#NIL DO
		MarkNeeded(dictFollow,TSIZE(dictRec),fresh);
		dictFollow:=dictFollow^.next
	END;
	FOR i:=0 TO LastEntry DO
		wdCurrent:=top^.info[i];
		WHILE wdCurrent#NIL DO
			MarkNeeded(wdCurrent,TSIZE(wordType),fresh);
			WITH wdCurrent^ DO
				MarkString(name);
				MarkClosure(def);
				MarkClosure(entry);
				wdCurrent:=next
			END
		END
	END
END MarkWords;

PROCEDURE FindWord(wd:ARRAY OF CHAR):link;
VAR
	follow:wordPtr;
	letter:CARDINAL;
BEGIN
	follow:=top^.info[HashString(wd,MaxEntries)];
	WHILE follow#NIL DO
		IF follow^.name^[0]=wd[0] THEN
			letter:=1;
			WITH follow^ DO
				WHILE (wd[letter]=name^[letter]) AND (name^[letter]#0C) DO
					INC(letter)
				END;
				IF wd[letter]=name^[letter] THEN
					RETURN ADR(def)
				END;
			END
		END;
		follow:=follow^.next
	END;
	RETURN NIL
END FindWord;

(*# call( o_a_copy => on ) *)

PROCEDURE FindWordNoCase(wd:ARRAY OF CHAR):link;
VAR
	follow:wordPtr;
	letter:CARDINAL;
BEGIN
	Caps(wd);
	follow:=top^.info[HashString(wd,MaxEntries)];
	WHILE follow#NIL DO
		IF CAP(follow^.name^[0])=wd[0] THEN
			letter:=1;
			WITH follow^ DO
				WHILE (wd[letter]=CAP(name^[letter])) AND (name^[letter]#0C) DO
					INC(letter)
				END;
				IF wd[letter]=name^[letter] THEN
					RETURN ADR(def)
				END;
			END
		END;
		follow:=follow^.next
	END;
	RETURN NIL
END FindWordNoCase;

PROCEDURE DefName(dp:link):ADDRESS;
TYPE
	AddrPtr=POINTER TO ADDRESS;
BEGIN
	RETURN AddrPtr(AddAddr(dp,TSIZE(closure)))^
END DefName;

PROCEDURE DefEntry(dp:link):closure;
BEGIN
	RETURN link(AddAddr(dp, TSIZE(closure) + TSIZE(ADDRESS)))^
END DefEntry;

PROCEDURE SetDefEntry(dp:link;newEntry:closure);
VAR
	entry:link;
BEGIN
	entry:=link(AddAddr(dp, TSIZE(closure) + TSIZE(ADDRESS)));
	SaveDefinition(entry);
	entry^:=newEntry
END SetDefEntry;

VAR
	name:closure;		(* unmarked temporary, used only during initialisation *)

BEGIN
	AddMarker( MarkWords );
	NEW(top);
	top^.next:=NIL;
	FOR i:=0 TO LastEntry DO
		top^.info[i]:=NIL
	END;

	AddArgument(wEntry, 'Entry');
	tempDef:=DefEntry(wEntry);
	RemoveEnv(tempDef,wMeaning);
	RemoveEnv(tempDef,wName);

	DefineWord(wParent, 'Parent', HandleParent);
	tempDef:=DefEntry(wParent);
	RemoveEnv(tempDef,wMeaning);
	RemoveEnv(tempDef,wName);

	AddAtom(wUndefined, 'Undefined');
	tempDef:=DefEntry(wUndefined);
	RemoveEnv(tempDef,wMeaning);
	RemoveEnv(tempDef,wName);
	MakeDef(UndefinedMeaning,wUndefined);
	parent:= UndefinedMeaning;

	AddArgument(wMeaning,'Meaning');
	tempDef:=DefEntry(wMeaning);
	RemoveEnv(tempDef,wName);

	AddArgument(wName,'Name');

	DefineWord(wString,'STRING',HandlePackage);

	MakeString(name,wString,DefName(wName));
	tempDef:=DefEntry(wName);
	AddEnv(tempDef,wName,name);

	MakeString(name,wString,DefName(wMeaning));
	tempDef:=DefEntry(wMeaning);
	AddEnv(tempDef,wName,name);

	MakeString(name,wString,DefName(wUndefined));
	tempDef:=DefEntry(wUndefined);
	AddEnv(tempDef,wName,name);
	MakeDef(name,wUndefined);
	AddEnv(tempDef,wMeaning,name);

	MakeString(name,wString,DefName(wParent));
	tempDef:=DefEntry(wParent);
	AddEnv(tempDef,wName,name);
	MakeDef(name,wParent);
	AddEnv(tempDef,wMeaning,name);

	MakeString(name,wString,DefName(wEntry));
	tempDef:=DefEntry(wEntry);
	AddEnv(tempDef,wName,name);
	MakeDef(name,wEntry);
	AddEnv(tempDef,wMeaning,name);
	wEntry^:=UndefinedMeaning;

	tempDef:=EmptyClosure
END Names.