packages feed

language-oberon-0.1.1: examples/AGRS/Library.Mod

MODULE Library;
IMPORT AGRS,Names,Texts,TextFrames;


CONST 
   (* Kodovi gresaka koji su sadrzani u tipu podataka Error. *)
   NotLogicalType*= 0;
   NotNumberType*= 1;
   NotCharacterType*= 2;
   NotStringType*= 3;
   NotTextType*= 4;
   NotFound*= 5;
   SyntaxError*= 6;

   CharSetLength= 256 DIV (MAX(SET)+1);

TYPE
   Term= AGRS.Term;
   ErrorType= INTEGER;

   NamesType= POINTER TO RECORD(AGRS.ClosedClassDesc)
   END;

   Number*= POINTER TO RECORD(AGRS.AtomicDesc)
      value*: INTEGER;
   END;

   String*= POINTER TO RECORD(AGRS.AtomicDesc)
      value-: Names.CharPtr;
   END;

   Text*= POINTER TO RECORD(AGRS.AtomicDesc)
      base-: Texts.Text;
      startOffset-,endOffset-: LONGINT;
   END;

   Character*= POINTER TO RECORD(AGRS.AtomicDesc)
      value-: CHAR;
   END;

   CharSet*= POINTER TO RECORD( AGRS.AtomicDesc)
      value-: ARRAY CharSetLength OF SET;
   END;

   Error*= POINTER TO RECORD(AGRS.AtomicDesc)
      value-: ErrorType;
   END;
   
   BinOp= POINTER TO RECORD(AGRS.TermDesc)
   END;
VAR
   TrueDef: Term;

   disTerm: AGRS.Disjunction;
   NamesTerm: NamesType;

   atomicName,numberName*,errorName*: AGRS.Name;
   charName*,stringName*,textName*,charSetName*: AGRS.Name;
   ifName,orName,andName,notName,testName,yesName,noName: AGRS.Name;
   addName*,subName*,mulName*,divName,modName: AGRS.Name;
   argName1*,argName2*: AGRS.Name;
   equalName,lessName,greaterName,lessEqName,grEqName: AGRS.Name;
   trueName*,disName,unifyName: AGRS.Name;
   abortName*,findName,nameName: AGRS.Name;
   carName,cdrName,consName,nilName: AGRS.Name;
   namesName: AGRS.Name;
   


PROCEDURE NewNumber*(v: INTEGER): Number;
VAR
   result: Number;
BEGIN
   NEW(result);
   result.Init(numberName);
   result.value:= v;
   AGRS.eldestAsked:= AGRS.Fixed;
   RETURN result;
END NewNumber;

PROCEDURE NewString*(v: Names.CharPtr): String;
VAR
   result: String;
BEGIN
   NEW(result);
   result.Init(stringName);
   result.value:= v;
   AGRS.eldestAsked:= AGRS.Fixed;
   RETURN result;
END NewString;

PROCEDURE NewChar*(v: CHAR): Character;
VAR
   result: Character;
BEGIN
   NEW(result);
   result.Init(charName);
   result.value:= v;
   AGRS.eldestAsked:= AGRS.Fixed;
   RETURN result;
END NewChar;

PROCEDURE NewCharSet*(): CharSet;
VAR
   result: CharSet;
   i: INTEGER;
BEGIN
   NEW(result);
   result.Init(charSetName);
   FOR i:= 0 TO CharSetLength-1 DO
      result.value[i]:= {};
   END;
   AGRS.eldestAsked:= AGRS.Fixed;
   RETURN result;
END NewCharSet;

   
PROCEDURE (t: String) Length*(): LONGINT;
VAR
   i: LONGINT;
   str: Names.CharPtr;
BEGIN
   i:= 0;
   str:= t.value;
   WHILE str[i]#0X DO
      INC(i);
   END;
   RETURN i
END Length;


PROCEDURE (t: CharSet) Include*(ch: CHAR);
BEGIN
   INCL(t.value[ORD(ch) DIV (MAX(SET)+1)],ORD(ch) MOD (MAX(SET)+1));
END Include;

PROCEDURE (t: CharSet) Complement*();
VAR
   i: INTEGER;
BEGIN
   FOR i:= 0 TO CharSetLength-1 DO
      t.value[i]:= -t.value[i];
   END;
END Complement;

PROCEDURE NewError*(v: ErrorType): Error;
VAR
   result: Error;
BEGIN
   NEW(result);
   result.Init(errorName);
   AGRS.eldestAsked:= AGRS.Fixed;
   result.value:= v;
   RETURN result
END NewError;

PROCEDURE SubText*(txt: Texts.Text; startPos,endPos: LONGINT): Text;
VAR
   newTerm: Text;
BEGIN
   NEW(newTerm);
   newTerm.Init(textName);
   newTerm.base:= txt;
   newTerm.startOffset:= startPos;
   newTerm.endOffset:= endPos;
   RETURN newTerm
END SubText;


PROCEDURE (t: Text) AppendText*(appendage: Text);
VAR
   temp: Texts.Buffer;
   newText: Texts.Text;
BEGIN
   IF (t.base=appendage.base) & (t.endOffset=appendage.startOffset) THEN
      t.endOffset:= appendage.endOffset;
   ELSE
      newText:= TextFrames.Text("");
      NEW(temp);
      Texts.OpenBuf(temp);
      Texts.Save(t.base,t.startOffset,t.endOffset,temp);
      Texts.Save(appendage.base,appendage.startOffset,appendage.endOffset,temp);
      Texts.Append(newText,temp);
      t.base:= newText;
      t.startOffset:= 0;
      t.endOffset:= newText.len;
   END;
END AppendText;

PROCEDURE (t: Text) AppendBuffer*(appendage: Texts.Buffer);
VAR
   newText: Texts.Text;
BEGIN
   IF t.endOffset=t.base.len THEN
      Texts.Append(t.base,appendage);
      t.endOffset:= t.base.len;
   ELSE
      newText:= TextFrames.Text("");
      Texts.Append(newText,appendage);
      t.base:= newText;
      t.startOffset:= 0;
      t.endOffset:= newText.len;
   END;
END AppendBuffer;


PROCEDURE (t: NamesType) Evaluate*(query: Term): Term;
BEGIN
   RETURN NewString(Names.NameSpelling(query.indirection))
END Evaluate;


PROCEDURE pType;
VAR
   newTerm: AGRS.OpenTree;
BEGIN
   NEW(newTerm);
   newTerm.Init(AGRS.lastResult);
   AGRS.result:= newTerm;
END pType;


PROCEDURE (t: Character) Compare*(reference: Term; VAR lessEq,grEq: BOOLEAN);
BEGIN
   WITH reference: Character DO
      lessEq:= t.value<=reference.value;
      grEq:= t.value>=reference.value;
   ELSE
      WITH reference: String DO
         lessEq:= t.value<=reference.value[0];
         grEq:= t.value>=reference.value[0];
         IF lessEq & grEq THEN
            grEq:= reference.value[1]=0X;
         END;
      ELSE
         lessEq:= FALSE;
         grEq:= FALSE;
      END;
   END;
END Compare;

PROCEDURE (t: String) Compare*(reference: AGRS.Term; VAR lessEq,grEq: BOOLEAN);
VAR
   i: INTEGER;
BEGIN
   WITH reference: Character DO
      lessEq:= t.value[0]<=reference.value;
      grEq:= t.value[0]>=reference.value;
      IF lessEq & grEq THEN
         lessEq:= t.value[1]=0X;
      END;
   ELSE
      WITH reference: String DO
         i:= 0;
         WHILE (t.value[i]=reference.value[i]) & (t.value[i]#0X) DO
            INC(i);
         END;
         lessEq:= (t.value[i]<=reference.value[i]);
         grEq:= (t.value[i]>=reference.value[i]);
      ELSE
         lessEq:= FALSE;
         grEq:= FALSE;
      END;
   END;
END Compare;

PROCEDURE (t: Number) Compare*(reference: Term; VAR lessEq,grEq: BOOLEAN);
BEGIN
   WITH reference: Number DO
      lessEq:= t.value<=reference.value;
      grEq:= t.value>=reference.value;
   ELSE
      lessEq:= FALSE;
      grEq:= FALSE;
   END;
END Compare;

PROCEDURE (t: CharSet) Compare*(reference: Term; VAR lessEq,grEq: BOOLEAN);
VAR
   i: INTEGER;
BEGIN
   lessEq:= TRUE;
   grEq:= TRUE;
   WITH reference: CharSet DO
      FOR i:= 0 TO CharSetLength-1 DO
         IF t.value[i]-reference.value[i]#{} THEN
            lessEq:= FALSE;
         END;
         IF reference.value[i]-t.value[i]#{} THEN
            grEq:= FALSE;
         END;
      END;
   ELSE
   END;
END Compare;

PROCEDURE (t: Error) Compare*(reference: Term; VAR lessEq,grEq: BOOLEAN);
BEGIN
   WITH reference: Error DO
      lessEq:= t.value<=reference.value;
      grEq:= t.value>=reference.value;
   ELSE
      lessEq:= FALSE;
      grEq:= FALSE;
   END;
END Compare;


PROCEDURE pEqual;
VAR
   t1,t2: AGRS.Term;
BEGIN
   t1:= argName1.Value();
   t2:= argName2.Value();
   IF AGRS.Equal(t1,t2) THEN
      TrueDef.Reduce;
   ELSE
      AGRS.Fail;
   END;
END pEqual;

PROCEDURE pLess;
VAR
   t1,t2: AGRS.Term;
   lessEq,grEq: BOOLEAN;
BEGIN
   t1:= argName1.Value();
   WITH t1: AGRS.Atomic DO
      t2:= argName2.Value();
      t1.Compare(t2,lessEq,grEq);
      IF lessEq & ~grEq THEN
         TrueDef.Reduce;
         RETURN
      END;
   END;
   AGRS.Fail;
END pLess;

PROCEDURE pGreater;
VAR
   t1,t2: AGRS.Term;
   lessEq,grEq: BOOLEAN;
   oldStack: AGRS.TermStack;
BEGIN
   t1:= argName1.Value();
   WITH t1: AGRS.Atomic DO
      t2:= argName2.Value();
      t1.Compare(t2,lessEq,grEq);
      IF ~lessEq & grEq THEN
         TrueDef.Reduce;
         RETURN
      END;
   END;
   AGRS.Fail;
END pGreater;

PROCEDURE pLessEq;
VAR
   t1,t2: AGRS.Term;
   lessEq,grEq: BOOLEAN;
BEGIN
   t1:= argName1.Value();
   WITH t1: AGRS.Atomic DO
      t2:= argName2.Value();
      t1.Compare(t2,lessEq,grEq);
      IF lessEq THEN
         TrueDef.Reduce;
         RETURN
      END;
   END;
   AGRS.Fail;
END pLessEq;

PROCEDURE pGrEq;
VAR
   t1,t2: AGRS.Term;
   lessEq,grEq: BOOLEAN;
BEGIN
   t1:= argName1.Value();
   WITH t1: AGRS.Atomic DO
      t2:= argName2.Value();
      t1.Compare(t2,lessEq,grEq);
      IF grEq THEN
         TrueDef.Reduce;
         RETURN
      END;
   END;
   AGRS.Fail;
END pGrEq;

PROCEDURE pNot;
BEGIN
   AGRS.result:= argName1.Value();
   IF AGRS.result.indirection=trueName THEN
      AGRS.result:= AGRS.Failure;
   ELSIF AGRS.result.indirection=AGRS.failName THEN
      AGRS.result:= TrueDef;
   ELSE
      AGRS.result:= NewError(NotLogicalType);
   END;
   AGRS.result.Reduce;
END pNot;

PROCEDURE pAnd;
VAR
   eldest1: INTEGER;
BEGIN
   AGRS.result:= argName1.Value();
   IF AGRS.result.indirection=trueName THEN
      eldest1:= AGRS.eldestAsked;
      AGRS.result:= argName2.Value();
      IF eldest1<AGRS.eldestAsked THEN
         AGRS.eldestAsked:= eldest1;
      END;
   ELSIF AGRS.result.indirection#AGRS.failName THEN
      AGRS.result:= NewError(NotLogicalType);
   END;
   AGRS.result.Reduce;
END pAnd;

PROCEDURE pOr;
VAR
   eldest1: INTEGER;
BEGIN
   AGRS.result:= argName1.Value();
   IF AGRS.result.indirection=AGRS.failName THEN
      eldest1:= AGRS.eldestAsked;
      AGRS.result:= argName2.Value();
      IF eldest1<AGRS.eldestAsked THEN
         AGRS.eldestAsked:= eldest1;
      END;
   ELSIF AGRS.result.indirection#trueName THEN
      AGRS.result:= NewError(NotLogicalType);
   END;
   AGRS.result.Reduce;
END pOr;


PROCEDURE pIf;
VAR
   eldest1: INTEGER;
BEGIN
   AGRS.result:= testName.Value();
   eldest1:= AGRS.eldestAsked;
   IF AGRS.result.indirection=trueName THEN
      yesName.Reduce;
   ELSIF AGRS.result.indirection=AGRS.failName THEN
      noName.Reduce;
   ELSE
      AGRS.result:= NewError(NotLogicalType);
      AGRS.result.Reduce;
   END;
   IF eldest1<AGRS.eldestAsked THEN
      AGRS.eldestAsked:= eldest1;
   END;
END pIf;


PROCEDURE ExtractNumbers(VAR x,y:INTEGER):BOOLEAN;
VAR
   eldest1: INTEGER;
   arg: Term;
BEGIN
   arg:= argName1.Value();
   WITH arg: Number DO
      x:= arg.value;
   ELSE
      RETURN FALSE
   END;
   eldest1:= AGRS.eldestAsked;
   arg:= argName2.Value();
   WITH arg: Number DO
      y:= arg.value;
   ELSE
      RETURN FALSE
   END;
   IF eldest1<AGRS.eldestAsked THEN
      AGRS.eldestAsked:= eldest1;
   END;
   RETURN TRUE
END ExtractNumbers;

PROCEDURE ExtractNumbersFromStack(VAR x,y:INTEGER; VAR oldStack:AGRS.TermStack):BOOLEAN;
VAR
   arg: Term;
BEGIN
   IF (AGRS.paramStack=NIL) OR (AGRS.paramStack.rest=NIL) THEN
      RETURN FALSE
   END;
   oldStack:= AGRS.paramStack;
   arg:= AGRS.paramStack.top;
   WITH arg: Number DO
      x:= arg.value;
   ELSE
      RETURN FALSE
   END;
   AGRS.paramStack:= AGRS.paramStack.rest;
   arg:= AGRS.paramStack.top;
   WITH arg: Number DO
      y:= arg.value;
   ELSE
      RETURN FALSE
   END;
   AGRS.paramStack:= AGRS.paramStack.rest;
   RETURN TRUE
END ExtractNumbersFromStack;

PROCEDURE pAdd;
VAR
   x,y:INTEGER;
   newTerm: Term;
   oldStack: AGRS.TermStack;
BEGIN
   IF ExtractNumbers(x,y) THEN
      newTerm:= NewNumber(x+y);
      newTerm.Reduce;
   ELSE
      AGRS.Continue;
   END;
END pAdd;

PROCEDURE pSub;
VAR
   x,y:INTEGER;
   newTerm: Term;
BEGIN
   IF ExtractNumbers(x,y) THEN
      newTerm:= NewNumber(x-y);
      newTerm.Reduce;
   ELSE
      AGRS.Continue;
   END;
END pSub;

PROCEDURE pMul;
VAR
   x,y:INTEGER;
   newTerm: Term;
BEGIN
   IF ExtractNumbers(x,y) THEN
      newTerm:= NewNumber(x*y);
      newTerm.Reduce;
   ELSE
      AGRS.Continue;
   END;
END pMul;

PROCEDURE pDiv;
VAR
   x,y:INTEGER;
   newTerm: Term;
BEGIN
   IF ExtractNumbers(x,y) THEN
      newTerm:= NewNumber(x DIV y);
      newTerm.Reduce;
   ELSE
      AGRS.Continue;
   END;
END pDiv;

PROCEDURE pMod;
VAR
   x,y:INTEGER;
   newTerm: Term;
BEGIN
   IF ExtractNumbers(x,y) THEN
      newTerm:= NewNumber(x MOD y);
      newTerm.Reduce;
   ELSE
      AGRS.Continue;
   END;
END pMod;


PROCEDURE pFind;
VAR
   s,n: Term;
BEGIN
   s:= nameName.Value();
   WITH s: String DO
      n:= Names.FindPublicName(s.value^);
      IF n=NIL THEN
         n:= NewError(NotFound);
      END;
   ELSE
      n:= NewError(NotStringType);
   END;
   n.Reduce;
END pFind;

PROCEDURE pAbort;
VAR
   stack: AGRS.TermStack;
BEGIN
   stack:= AGRS.continuation;
   HALT(255)
END pAbort;

PROCEDURE pUnify;
BEGIN
   AGRS.Push(trueName);
   AGRS.Unify(argName1.indirection,argName2.Value());
END pUnify;

PROCEDURE (t: BinOp) Reduce*;
BEGIN
   AGRS.Push(t.indirection);
   AGRS.Push(argName2.indirection);
   argName1.Reduce;
END Reduce;

PROCEDURE AddBinOp(proc:AGRS.HandlerType; name,primName: ARRAY OF CHAR);
VAR
   newTerm: BinOp;
   newName: AGRS.Name;
BEGIN
   Names.AddSystemName(newName,primName,proc);
   NEW(newTerm);
   newTerm.Init(newName);
   Names.DefinePublicName(newName,name,newTerm);
END AddBinOp;

BEGIN
   Names.AddSystemName(atomicName,'AtomSystemRoot',AGRS.AtomicHandler);
   Names.DefinePublicName(textName,'TEXT',atomicName.indirection);
   Names.DefinePublicName(stringName,'STRING',atomicName.indirection);
   Names.DefinePublicName(charName,'CHAR',atomicName.indirection);
   Names.DefinePublicName(charSetName,'CharSET',atomicName.indirection);
   Names.DefinePublicName(errorName,'ERROR',atomicName.indirection);
   Names.DefinePublicName(numberName,'NUMBER',atomicName.indirection);

   Names.AddArgument(carName, 'Car');
   Names.AddArgument(cdrName, 'Cdr');
   Names.AddArgument(nilName, 'Nil');
   Names.AddArgument(consName, 'Cons');

   Names.AddArgument(trueName, 'True');
   NEW(TrueDef);
   TrueDef.Init(trueName);
   Names.AddSystemName(andName, 'And', pAnd);
   Names.AddSystemName(orName, 'Or', pOr);
   Names.AddSystemName(notName, 'Not', pNot);
   Names.AddSystemName(ifName, 'If', pIf);
   Names.AddArgument(testName, 'Test');
   Names.AddArgument(yesName, 'Yes');
   Names.AddArgument(noName, 'No');

   argName1:= Names.FindOrdinalName(1);
   argName2:= Names.FindOrdinalName(2);

   NEW(disTerm);
   disTerm.Init(argName1);
   disTerm.InitAlternative(argName2);
   Names.DefinePublicName(disName, 'Dis', disTerm);

   Names.AddSystemName(AGRS.failName,'Fail',AGRS.Fail);
   Names.AddSystemName(unifyName, 'Unify', pUnify);
   Names.AddSystemName(equalName, 'Equal', pEqual);
   Names.AddSystemName(lessName, 'Less', pLess);
   Names.AddSystemName(greaterName, 'Greater', pGreater);
   Names.AddSystemName(lessEqName, 'LessEq', pLessEq);
   Names.AddSystemName(grEqName, 'GrEq', pGrEq);
   NEW(AGRS.Failure);
   AGRS.Failure.Init(AGRS.failName);

   Names.AddSystemName(addName, 'Add', pAdd);
   Names.AddSystemName(subName, 'Sub', pSub);
   Names.AddSystemName(mulName, 'Mul', pMul);
   Names.AddSystemName(divName, 'Div', pDiv);
   Names.AddSystemName(modName, 'Mod', pMod);
   Names.AddSystemName(findName, 'Find', pFind);
   Names.AddSystemName(abortName, 'Abort', pAbort);

   NEW(NamesTerm);
   NamesTerm.Init(Names.SystemRoot);
   Names.DefinePublicName(namesName,'Names',NamesTerm);
END Library.