home *** CD-ROM | disk | FTP | other *** search
- (*****************************************************************************)
- (* CALCSIM2.PAS *)
- (* *)
- (* Vereinfachen von Calc-Programmen Teil 2 *)
- (*****************************************************************************)
- {$a-}
-
- PROCEDURE simple(pptr : calc_prog);
-
- VAR pptra,pptrb : calc_prog;
-
- PROCEDURE restoreptr;
-
- BEGIN
- pptra := pptr^.nextinst;
- pptrb := endof(pptra);
- IF pptrb <> nil
- THEN
- pptrb := pptrb^.nextinst;
- END;
-
- PROCEDURE erase_entry;
-
- BEGIN
- WHILE help1 <> pptrb DO
- BEGIN
- help2 := help1;
- help1 := help1^.nextinst;
- Dispose(help2)
- END;
- END;
-
- PROCEDURE pusha;
-
- BEGIN
- pptr^ := pptra^;
- help1 := pptr;
- WHILE help1^.nextinst <> pptrb DO
- help1 := help1^.nextinst;
- help1^.nextinst := pptrb^.nextinst;
- Dispose(pptra);
- Dispose(pptrb);
- restoreptr
- END;
-
- PROCEDURE skipa;
-
- BEGIN
- help1 := pptr^.nextinst;
- erase_entry;
- pptr^ := pptrb^;
- Dispose(pptrb);
- restoreptr
- END;
-
- PROCEDURE setconst(dummy : calc_operand);
-
- BEGIN
- pptr^.instruct := calc_const;
- pptr^.operand := dummy;
- pptr^.nextinst := pptrb^.nextinst;
- help1 := pptra;
- erase_entry;
- Dispose(pptrb);
- restoreptr
- END;
-
- BEGIN
- IF pptr <> nil
- THEN
- BEGIN
- restoreptr;
- IF pptr^.instruct IN [calc_neg,calc_sqr..calc_fak]
- THEN
- BEGIN
- simple(pptra);
- IF pptra^.instruct = calc_const
- THEN (* ausrechnen ! *)
- BEGIN
- dummy := compute(pptr, pptra,nil);
- (* leider ist 0.0 <> -0.0 deshalb : *)
- IF dummy = -0.0
- THEN
- dummy := 0.0;
- pptr^.instruct := calc_const;
- pptr^.operand := dummy;
- pptr^.nextinst := pptra^. nextinst;
- Dispose(pptra);
- restoreptr
- END;
- IF pptr^.instruct = calc_neg
- THEN
- BEGIN
- IF pptra^.instruct = calc_neg
- THEN
- BEGIN
- pptr^ := pptra^.nextinst^;
- Dispose(pptra^.nextinst);
- Dispose(pptra);
- restoreptr
- END
- END;
- IF (pptr^.instruct = calc_neg) AND(pptra^.instruct IN [
- calc_mul.. calc_div])
- THEN
- BEGIN
- help1 := endof(pptra^.nextinst);
- IF pptra^.nextinst^.instruct = calc_const
- THEN
- BEGIN
- pptra^.nextinst^.operand := -pptra^.nextinst^.
- operand;
- pptr^ := pptra^;
- Dispose(pptra);
- restoreptr;
- END
- ELSE
- IF help1^.nextinst^.instruct = calc_const
- THEN
- BEGIN
- help1^.nextinst^.operand := - help1^.
- nextinst^.
- operand;
- pptr^ := pptra^;
- Dispose(pptra);
- restoreptr;
- END
- END;
- END
- ELSE (* jetzt werden Operationen mit Konstanten vereinfacht *)
- IF pptr^.instruct IN [calc_add..calc_pow]
- THEN
- BEGIN
- simple(pptra);
- simple(pptrb);
- arg1 := pptra^.instruct = calc_const;
- arg2 := pptrb^.instruct = calc_const;
- IF arg1 AND arg2
- THEN
- BEGIN
- dummy := compute(pptr,pptrb,pptra);
- pptr^.instruct := calc_const;
- pptr^.operand := dummy;
- pptr^.nextinst := pptrb^.nextinst;
- Dispose(pptra);
- Dispose(pptrb);
- restoreptr
- END
- ELSE
- IF arg2
- THEN
- BEGIN
- IF pptrb^.operand = 0.0
- THEN
- BEGIN
- IF pptr^.instruct IN[calc_mul.. calc_div,
- calc_pow]
- THEN
- setconst(0.0)
- ELSE
- IF pptr^.instruct = calc_add
- THEN
- pusha
- ELSE
- IF pptr^.instruct = calc_sub
- THEN
- BEGIN
- pptr^.instruct := calc_neg;
- help1 := endof(pptra);
- help1^.nextinst := pptrb^.
- nextinst
- ;
- Dispose(pptrb);
- restoreptr
- END
- END
- ELSE
- IF (pptrb^.operand = 1.0) AND(pptr^.
- instruct IN[ calc_mul, calc_pow])
- THEN
- BEGIN
- IF pptr^.instruct = calc_mul
- THEN
- pusha
- ELSE
- setconst(1.0)
- END
- END
- ELSE
- IF arg1
- THEN
- BEGIN
- IF pptra^.operand = 0.0
- THEN
- BEGIN
- IF pptr^.instruct IN[ calc_mul,
- calc_pow]
- THEN
- BEGIN
- IF pptr^.instruct = calc_mul
- THEN
- dummy := 0.0
- ELSE
- dummy := 1.0;
- pptr^.instruct := calc_const;
- pptr^.operand := dummy;
- help1 := pptrb;
- op := 1;
- REPEAT
- help2 := help1;
- IF help1^.instruct IN[
- calc_add.. calc_pow]
- THEN
- op := Succ(op)
- ELSE
- IF help1^.instruct IN[
- calc_const, calc_var]
- THEN
- op := Pred(op);
- help1 := help1^.nextinst;
- Dispose(help2);
- UNTIL op = 0;
- pptr^.nextinst := help1;
- Dispose(pptra);
- restoreptr
- END
- ELSE
- IF pptr^.instruct IN [ calc_add,
- calc_sub]
- THEN
- skipa
- END
- ELSE
- IF (pptra^.operand = 1.0) AND( pptr^.
- instruct IN [ calc_mul..calc_div,
- calc_pow])
- THEN
- skipa;
- END;
- IF (pptr^.instruct = calc_mul) AND(pptra^.instruct IN [
- calc_div,calc_dvd])
- THEN
- BEGIN
- help1 := endof(pptra^.nextinst);
- IF (help1^.nextinst^.instruct = calc_const)
- THEN
- IF help1^.nextinst^.operand = 1.0
- THEN
- BEGIN
- pptr^ := pptra^;
- Dispose(pptra);
- Dispose(help1^.nextinst);
- help1^.nextinst := pptrb;
- restoreptr
- END
- ELSE
- IF help1^.nextinst^.operand = -1.0
- THEN
- BEGIN
- pptr^.instruct := calc_neg;
- Dispose(help1^.nextinst);
- help1^.nextinst := pptrb;
- restoreptr
- END;
- END;
- IF pptr^.instruct IN [calc_mul..calc_div]
- THEN
- BEGIN (* Negationen vereinfachen *)
- IF pptra^.instruct = calc_neg
- THEN
- IF pptrb^.instruct = calc_neg
- THEN
- BEGIN
- pptr^.nextinst := pptra^.nextinst;
- Dispose(pptra);
- pptra := pptr^.nextinst;
- help1 := endof(pptra);
- help1^.nextinst := pptrb^.nextinst;
- Dispose(pptrb);
- restoreptr;
- END
- ELSE
- BEGIN
- IF ((pptrb^.instruct = calc_const) AND(
- pptrb^. operand < 0.0))
- THEN
- BEGIN
- pptr^.nextinst := pptra^.nextinst;
- Dispose(pptra);
- pptrb^.operand := Abs(pptrb^.
- operand);
- restoreptr
- END
- END
- ELSE
- IF ((pptra^.instruct = calc_const) AND ( pptra^
- . operand< 0.0))
- THEN
- IF pptrb^.instruct = calc_neg
- THEN
- BEGIN
- pptra^.nextinst := pptrb^.nextinst;
- Dispose(pptrb);
- pptra^.operand := Abs(pptra^. operand
- );
- restoreptr
- END;
- IF (pptra^.instruct = calc_const) AND(pptra^.
- operand = - 1.0)
- THEN
- BEGIN
- pptr^.instruct := calc_neg;
- pptr^.nextinst := pptrb;
- Dispose(pptra);
- restoreptr
- END;
- IF ((pptrb^.instruct = calc_const) AND (pptrb^.
- operand =- 1.0) AND (pptr^.instruct = calc_mul)
- )
- THEN
- BEGIN
- help1 := endof(pptra);
- help1^.nextinst := pptrb^.nextinst;
- pptr^.instruct := calc_neg;
- Dispose(pptrb);
- restoreptr
- END;
- END;
- IF (pptr^.instruct = calc_add) AND (pptra^.instruct =
- calc_neg)
- THEN
- BEGIN
- pptr^.instruct := calc_sub;
- pptr^.nextinst := pptra^.nextinst;
- Dispose(pptra);
- restoreptr
- END;
- IF (pptr^.instruct = calc_sub) AND (pptra^.instruct =
- calc_neg)
- THEN
- BEGIN
- pptr^.instruct := calc_add;
- pptr^.nextinst := pptra^.nextinst;
- Dispose(pptra);
- restoreptr
- END;
- (* jetzt wird's schwierig : das Kommutativgesetz *)
- IF (((pptr^.instruct = calc_mul) AND(pptra^. instruct IN[
- calc_mul..calc_div])) OR ((pptr^.instruct = calc_add)
- AND( pptra^.instruct IN[ calc_add, calc_sub]))) AND (
- pptrb^. instruct = calc_const)
- THEN
- BEGIN
- help1 := endof(pptra^.nextinst);
- help2 := endof(help1^.nextinst);
- IF pptra^.instruct IN [calc_mul,calc_add]
- THEN
- BEGIN
- IF help1^.nextinst^.instruct= calc_const
- THEN
- BEGIN
- help2^.nextinst := pptra^. nextinst;
- pptra^.nextinst := pptrb;
- help2 := pptrb^.nextinst;
- pptrb^.nextinst := help1^. nextinst;
- help1^.nextinst := help2;
- END
- ELSE
- IF pptra^.nextinst^.instruct= calc_const
- THEN
- BEGIN
- help2^.nextinst := pptrb^. nextinst
- ;
- pptrb^.nextinst := help1^. nextinst
- ;
- help1^.nextinst := pptrb;
- END;
- END
- ELSE
- BEGIN
- IF help1^.nextinst^.instruct= calc_const
- THEN
- BEGIN
- helpinstruct := pptr^.instruct;
- pptr^.instruct := pptra^. instruct;
- pptra^.instruct := helpinstruct;
- pptr^.nextinst := pptra^. nextinst;
- pptra^.nextinst := help1^. nextinst;
- help1^.nextinst := pptra;
- END;
- END;
- restoreptr;
- simple(pptra);
- simple(pptrb)
- END
- ELSE
- IF (((pptr^.instruct = calc_mul) AND (pptrb^.
- instruct IN[ calc_mul..calc_div])) OR (( pptr^.
- instruct = calc_add) AND(pptrb^. instruct IN[
- calc_add,calc_sub]))) AND( pptra^.instruct =
- calc_const)
- THEN
- BEGIN
- help1 := endof(pptrb^.nextinst);
- help2 := endof(help1^.nextinst);
- IF pptrb^.instruct IN [calc_add, calc_mul]
- THEN
- BEGIN
- IF pptrb^.nextinst^.instruct= calc_const
- THEN
- BEGIN
- pptr^.nextinst := help1^. nextinst;
- help1^.nextinst := pptra;
- pptra^.nextinst := help2^. nextinst
- ;
- help2^.nextinst := pptrb;
- END
- ELSE
- IF help1^.nextinst^.instruct=
- calc_const
- THEN
- BEGIN
- pptr^.nextinst := pptrb^.
- nextinst;
- pptra^.nextinst := help1^.
- nextinst;
- help1^.nextinst := pptrb;
- pptrb^.nextinst := pptra ;
- END
- END
- ELSE
- BEGIN
- IF help1^.nextinst^.instruct= calc_const
- THEN
- BEGIN
- helpinstruct := pptr^. instruct;
- pptr^.instruct := pptrb^. instruct;
- pptrb^.instruct := helpinstruct;
- pptr^.nextinst := pptrb^. nextinst;
- pptrb^.nextinst := pptra;
- pptra^.nextinst := help1^. nextinst
- ;
- help1^.nextinst := pptrb ;
- END;
- END;
- restoreptr;
- simple(pptra);
- simple(pptrb)
- END ;
- IF pptr^.instruct = calc_mul
- THEN
- BEGIN
- IF pptra^.instruct = calc_pow
- THEN
- BEGIN
- help2 := pptra^.nextinst;
- help1 := endof(help2);
- help1 := help1^.nextinst;
- IF (help2^.instruct = calc_const) AND equal(
- help1, pptrb)
- THEN
- BEGIN
- help2^.operand := help2^.operand + 1.0;
- pptr^ := pptra^;
- Dispose(pptra);
- help2^.nextinst := pptrb;
- erase_entry;
- restoreptr
- END
- END
- END;
- IF pptr^.instruct IN [calc_add,calc_sub,calc_dvd,
- calc_div, calc_mul]
- THEN
- IF equal(pptra,pptrb)
- THEN (* sind die Operanden gleich ? *)
- BEGIN
- CASE pptr^.instruct OF
- calc_add : BEGIN
- pptr^.instruct := calc_mul;
- help2 := endof(pptra);
- help1 := pptra^.nextinst;
- pptra^.instruct := calc_const;
- pptra^.operand := 2.0;
- pptra^.nextinst := help2^.
- nextinst;
- erase_entry;
- restoreptr
- END;
- calc_sub : setconst(0.0);
- calc_div,calc_dvd : setconst(1.0);
- calc_mul : BEGIN
- pptr^.instruct := calc_pow;
- help2 := endof(pptra);
- help1 := pptra^.nextinst;
- pptra^.nextinst := help2^.
- nextinst;
- pptra^.instruct := calc_const;
- pptra^.operand := 2.0;
- erase_entry;
- restoreptr
- END;
- END
- END;
- END;
- END
- END;
- {$a+}
-
- BEGIN
- IF pptr <> nil
- THEN
- BEGIN
- simpleerror := FALSE;
- calcresult := TRUE;
- invert(pptr);
- pptr1 := pptr^.nextinst;
- simple(pptr1);
- IF simpleerror
- THEN
- BEGIN
- killexpression(pptr);
- calcresult := FALSE
- END
- ELSE
- invert(pptr)
- END
- ELSE
- calcresult := FALSE
- END;
-