unit CalcAnsiScript; interface uses SysUtils , uAnsiCharTools {$IFDEF FPC} , LazUTF8 {$ENDIF} ; type TMyCalLabel = record nm: AnsiString; dt: Extended; end; TAMyCalLabel = array of TMyCalLabel; TCallFunc = function(const lab: string; const Labels: TAMyCalLabel): boolean of object; TExeLabel = function(const lab: string; var ret: Extended; cmd: TGetLabelCmd): boolean of object; TGetConst = function(const lab: string; out ret: Extended): boolean of object; //読込のみラベル TAnsiCalculate = class; TCalcuAddition = class(TObject) //追加機能 protected owner: TAnsiCalculate; //TAnsiCalculate. AddTCalcuAdditionで親が必ず設定してくれる public function FileExec(const fname: AnsiString; p: PChar): boolean; virtual; //fileを処理したらtrue function LineCmd(const lab: AnsiString; var p: PChar): boolean; virtual; //#で始まる行コマンド function CallFunc(const lab: AnsiString; Labels: TAMyCalLabel): boolean; virtual; //func()形式の関数 function ExeLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; virtual; //ラベルへの読書 procedure StartEndScript(n: Integer); virtual; //0:start 1:end; end; TCalcuAdditionClass = class of TCalcuAddition; TAnsiCalculate = class(TObject) private function formulaLineIn: boolean; protected Ext: array of TCalcuAddition; Labels: TAMyCalLabel; OutFmt: AnsiString; // opt: TCAnsiCalcOpt; p , LineSt, endp: PAnsiChar; procedure comp; procedure factor; procedure muldiv; procedure next; procedure Vshift; function CallFunc(const lab: AnsiString): boolean; virtual; function ExeLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; virtual; function constLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; virtual; procedure ConstPrint; procedure ExecInit; virtual; public OnCallFunc: TCallFunc; OnExeLabel: TExeLabel; OnGetConst: TGetConst; calcMode: Integer; //b0:代入文式でも最後の値を出力する ErrCount: Integer; MyCmd: AnsiString; //Createで渡された文字列 emsg: AnsiString; //putMsg エラーや結果出力 OutMsg: AnsiString; num: Extended; //結果値 CallParam: TAMyCalLabel; procedure addsub; //拡張機能がpの数値を得る為に呼び numを得る function EndCheck(p: PChar): boolean; //pが最初の終端を超えていないかチェック procedure Err(msg: AnsiString); virtual; procedure AddTCalcuAddition(add: TCalcuAdditionClass); procedure PutLine(add: string); virtual; procedure putMsg(msg: AnsiString); virtual; procedure MsgOut(msg: AnsiString); virtual; procedure MsgOutLn(msg: AnsiString); virtual; function formulaLine(cmd: string): boolean; constructor Create(cmd: AnsiString); destructor Destroy; override; function FileExec(const fname: AnsiString): boolean; virtual; //ファイルモードで特別な処理がある場合 procedure ExecCmd; //これで実行する end; function cvU(s: string): Ansistring; //文字コード変換 function addS(s: array of Ansistring): Ansistring; //文字コード連結 var CalcuAdditions: array of TCalcuAdditionClass = nil; procedure CalcAddTCalcuAddition(add: TCalcuAdditionClass); const ConstTable: array[0..7] of record d: Extended; n, h: AnsiString end = ((d: 3.1415926535897932384626433; n: 'PI'; h: '円周率'; ) , (d: 2.7182818284590452353602874; n: '_e'; h: 'オイラー数'; ) , (d: 299792458; n: '_c'; h: '光速 m/s'; ) , (d: 9.80665; n: '_g'; h: '重力加速度 m/s^2'; ) , (d: 6.62607015E-34; n: '_h'; h: 'プランク定数 J*s'; ) , (d: 1.380649E23; n: '_k'; h: 'ボルツマン定数 J/K'; ) , (d: 6.02214076E23; n: '_NA'; h: 'アボガドロ数 /mol'; ) , (d: 5.6703744191844E-8; n: 'σ'; h: 'シュテファンボルツマン定数'; ) ); implementation uses math; //Lazarusの為に UTF8をコンソール出力可能な文字に変換 function cvU(s: string): Ansistring; //文字コード変換 begin {$IFDEF FPC} Result := UTF8ToConsole(s); {$ELSE} Result := s; {$ENDIF} end; function addS(s: array of Ansistring): Ansistring; //文字コード連結 var len, i, n: integer; begin len := 0; for i := 0 to High(s) do len := len + length(s[i]); Setlength(result, len); n := 1; for i := 0 to High(s) do begin move(s[i][1], result[n], length(s[i])); inc(n, length(s[i])); end; end; { TAnsiCalculate } type TAChar3 = array[0..2] of AnsiChar; TAChar2 = array[0..1] of AnsiChar; pA3 = ^TAChar3; pA2 = ^TAChar2; procedure TAnsiCalculate.ConstPrint; var i: Integer; begin for i := 0 to High(ConstTable) do with ConstTable[i] do begin MsgOutLn(addS(['// ', n, ' #', cvU(h)])); end; end; procedure TAnsiCalculate.next; begin inc(p); end; procedure TAnsiCalculate.factor; var lab, s: AnsiString; i64: Int64; n: Integer; oldp: PAnsiChar; procedure inFuncParam(); begin SetLength(CallParam, n + 1); next; if p^ in ['''', '"'] then begin oldp := p; inc(p); s := CAnsiGetNextStr(p, [oldp^, #13, #10, #0]); if p^ <> oldp^ then Err(s + '?'); CallParam[n].nm := copy(s, 1, p - oldp - 1); end else addsub; CAnsiSkipBlank(p); CallParam[n].nm := ''; CallParam[n].dt := num; end; begin CAnsiSkipBlank(p); if (p^ = '(') then begin next; addsub; CAnsiSkipBlank(p); if (p^ <> ')') then raise EAbort.Create('):' + p^ + ' is NG'); next; end else begin if CAnsiGetAsmHex(p, i64) then begin num := i64; CAnsiSkipBlank(p); exit; end; if CAnsiGetAsmBin(p, i64) then begin num := i64; CAnsiSkipBlank(p); exit; end; if not CAnsiGetDotNumExt(p, num) then if (p^ in LabelTopCharSet + MyLeadBytes) then begin lab := CAnsiGetAccordZenChars(p, LabelCharSet); CAnsiSkipBlank(p); if p^ = '(' then begin n := 0; inFuncParam(); while p^ = ',' do begin inc(n); inFuncParam(); end; if (p^ <> ')') then Err(lab + '(... ")"?'); next; if not CallFunc(lab) then Err(lab + ' is not function '); end else begin if not ExeLabel(lab, num, glGetData) then Err(lab + ' undefined labels'); end; end else Exception.Create(p + ' is not numeric ') end; CAnsiSkipBlank(p); end; procedure TAnsiCalculate.Vshift; var savenum: Extended; oldsym: AnsiChar; begin factor; if (p^ in ['>', '<']) and (p^ = p[1]) and (not (csLLRR_NG in opt)) then begin savenum := num; oldsym := p^; inc(p, 2); factor; case oldsym of '>': num := ord(trunc(savenum) shr trunc(num)); //>> '<': num := ord(trunc(savenum) shl trunc(num)); //<< end; exit; end; if ((pA3(p)^ = 'SHL') or (pA3(p)^ = 'shl')) and (p[3] in [#9, ' ', '(', '$', '0'..'9']) then begin savenum := num; inc(p, 3); factor; num := round(savenum) shl round(num); exit; end else if ((pA3(p)^ = 'SHR') or (pA3(p)^ = 'shr') ) and (p[3] in [#9, ' ', '(', '$', '0'..'9']) then begin savenum := num; inc(p, 3); factor; num := round(savenum) shr round(num); exit; end; while (p^ in ['^']) do begin savenum := num; oldsym := p^; next; factor; case oldsym of '^': num := power(savenum, num); end; end; end; //== 等しい //!= 等しくない //< より小さい //> より大きい //<= 以下 //>= 以上 procedure TAnsiCalculate.comp; var savenum: Extended; oldsym: AnsiChar; begin Vshift; if (p^ in ['!', '=']) and (p[1] = '=') then begin savenum := num; oldsym := p^; inc(p, 2); Vshift; case oldsym of '!': num := ord(round(savenum) <> round(num)); '=': num := ord(round(savenum) = round(num)); end; end else if (p^ in ['>', '<']) and (not (p[1] in ['>', '<'])) then begin if p[1] = '=' then begin savenum := num; oldsym := p^; inc(p, 2); Vshift; case oldsym of '>': num := ord(savenum >= num); '<': num := ord(savenum <= num); end; end else begin savenum := num; oldsym := p^; inc(p); Vshift; case oldsym of '>': num := ord(savenum > num); '<': num := ord(savenum < num); end; end; end; end; procedure TAnsiCalculate.muldiv; var savenum: Extended; oldsym: AnsiChar; begin comp; while (p^ in ['*', '/', '^']) do begin if pA2(p)^ = '//' then exit; savenum := num; oldsym := p^; next; comp; try case oldsym of '^': num := power(savenum, num); '*': num := savenum * num; '/': num := savenum / num; end; except num := 0; end; end; end; procedure TAnsiCalculate.addsub; var savenum: Extended; oldsym: AnsiChar; lab: AnsiString; begin CAnsiSkipBlank(p); if pA2(p)^ = '//' then exit; if (p^ in ['!', '~']) or (pA3(p)^ = 'NOT') then begin oldsym := p^; inc(p); if oldsym = 'N' then inc(p, 2); addsub; case oldsym of '!': if num > 0.5 then num := ord(false) else num := ord(True); '~': num := $FFFFFF xor round(num); //24bitのビット反転 'N': num := not round(num); //ビット反転 end; end; if (p^ in ['+', '-']) then begin //+か-が前置されたら if p[0] = p[1] then begin //++ --演算子 oldsym := p^; CAnsiSkipBlank(p); if (p^ in ['$'] + LabelTopCharSet + MyLeadBytes) then begin lab := CAnsiGetAccordZenChars(p, LabelCharSet); case oldsym of '+': num := 1; '-': num := -1; end; if not ExeLabel(lab, num, glPrePP) then raise EAbort.Create(lab + ' undefined labels'); end else raise EAbort.Create('++/-- >label?'); end else begin oldsym := p^; next; case oldsym of '+': MulDiv; '-': begin MulDiv; num := -num; end; end end; end else muldiv; if ((pA3(p)^ = 'AND') or (pA3(p)^ = 'and') ) and (p[3] in [#9, ' ', '(', '$', '0'..'9']) then begin savenum := num; inc(p, 3); addsub; num := round(savenum) and round(num); exit; end else if ((pA2(p)^ = 'OR') or (pA2(p)^ = 'or') ) and (p[2] in [#9, ' ', '(', '$', '0'..'9']) then begin savenum := num; inc(p, 2); addsub; num := round(savenum) or round(num); exit; end else if (pA3(p)^ = 'XOR') or (pA3(p)^ = 'xor') then begin savenum := num; inc(p, 3); addsub; num := round(savenum) xor round(num); exit; end; while (p^ in ['+', '-', '&', '|']) do begin savenum := num; oldsym := p^; next; muldiv; case oldsym of '&': num := round(savenum) and round(num); '|': num := round(savenum) or round(num); '+': num := savenum + num; '-': num := savenum - num; end; end; end; function MyNumToStr(d: Extended): string; var c: string; begin Result := NumToStr(d, c); if c <> '' then Result := Result + format('(%g)', [d]); end; procedure TAnsiCalculate.ExecInit; begin p := PAnsiChar(MyCmd); SetLength(Labels, 0); OutMsg := ''; eMsg := ''; end; function TAnsiCalculate.formulaLineIn(): boolean; //数値で終わっていたら true 代入だけならfalse var lab: string; oldp: PAnsiChar; begin Result := false; oldp := p; //ラベルの後に=が無い場合に備えて保存 while True do begin if p^ in LabelTopCharSet + MyLeadBytes then begin oldp := p; //ラベルの後に=が無い場合に備えて保存 lab := CAnsiGetAccordZenChars(p, LabelCharSet); CAnsiSkipBlank(p); if ((p[0] = '=') and (p[1] <> '=')) or (pA2(p)^ = ':=') then begin {比較演算子でないなら} if p[0] = ':' then Inc(p); Inc(p); addsub; CAnsiSkipBlank(p); if not ExeLabel(lab, num, glSetData) then Err(lab + '?'); if not (p^ in [',', ';', ':']) then begin break; end; Next; //連続代入処理 CAnsiSkipBlank(p); if (p^ in [#0, #13, #10]) then break; end else begin {name = でないなら } p := oldp; break; end; end else break; //ラベルで始まっていない場合 end; CAnsiSkipBlank(p); if (pA2(p)^ = '//') then begin CAnsiGetNextStr(p, [#0, #13, #10]); //コメントなので改行まで読み捨て end else if not (p^ in [#0, #13, #10]) then begin addsub; Result := True; CAnsiSkipBlank(p); end; end; // //関数内等で文字列の数式を処理させるためのもの function TAnsiCalculate.formulaLine(cmd: string): boolean; //最後が数値で終わっていたら true 代入だけならfalse var oldp: PAnsiChar; begin oldp := p; try p := PAnsiChar(cmd); while p^ <> #0 do begin Result := formulaLineIn(); CAnsiSkip(p, [#9, ' ', #13, #10]) end; finally p := oldp; end; end; procedure TAnsiCalculate.ExecCmd; var lab: string; oldp: PAnsiChar; i: Integer; begin ErrCount := 0; ExecInit; for i := 0 to High(Ext) do Ext[i].StartEndScript(0); while p^ <> #0 do begin CAnsiSkip(p, [#9, ' ', #13, #10]); //先頭の空白は除く 改行文字も eMsg := ''; LineSt := p; if p^ = '#' then begin //先頭#は何か特殊処理に使う予定 while true do begin //Breakを使う為で無限ループではない inc(p); lab := CAnsiGetAccordZenChars(p, LabelCharSet); CAnsiSkipBlank(p); if lab = 'ScriptFile' then begin if p[0] <> '=' then Err('ScriptFileの後に=が無い'); PutLine(cvU('// 未実装')); break; end; if lab = 'fmt' then begin // 書式を付けられるようにしようかと思ったが反映させていない if p[0] <> '=' then Err(cvU('fmtの後に=が無い')); OutFmt := CAnsiGetNextStr(p, [#0, #13, #10]); PutLine(cvU('// 未実装')); break; end; if AnsiSameText(lab, cvU('定数')) then begin PutLine(''); ConstPrint; break; end; if AnsiSameText(lab, 'm') then begin CAnsiSkipBlank(p); addsub; calcMode := Round(num); break; end; if SameText(lab, 'h') or (lab = '') then //help begin PutLine(''); MsgOutLn(cvU('#定数 で 内部定数一覧'#13#10' !論理反転(0⇔1) NOT ビット反転 ~ 24bitビット反転')); end; for i := 0 to High(Ext) do if Ext[i].LineCmd(lab, p) then break; break; end; if p^ in [#0, #13, #10] then continue; //行先頭に戻る CAnsiGetNextStr(p, [#0, #13, #10]); //行の残りを読み飛ばす continue; end; //'#'処理終了 try if formulaLineIn() then begin if eMsg <> '' then PutLine(eMsg) else PutLine(MyNumToStr(num)); if not (p^ in [#0, #13, #10]) then CAnsiGetNextStr(p, [#0, #13, #10]); end else begin CAnsiGetNextStr(p, [#0, #13, #10]); if (calcMode and 1) <> 0 then PutLine(MyNumToStr(num)) else PutLine(''); //行をそのまま出力する end; except PutLine(eMsg); // CAnsiGetNextStr(p, [#0, #13, #10]); end; end; for i := 0 to High(Ext) do Ext[i].StartEndScript(1); end; procedure TAnsiCalculate.PutLine(add: string); var lin: string; sz: Integer; begin sz := p - LineSt; if sz > 0 then begin SetLength(lin, sz); move(LineSt^, lin[1], sz); end else lin := ''; if add <> '' then lin := lin + '//' + add; MsgOutLn(lin); end; procedure TAnsiCalculate.Err(msg: AnsiString); begin inc(ErrCount); putMsg('!Err:' + msg); raise EAbort.Create(msg); end; function TAnsiCalculate.constLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; var i: Integer; begin Result := false; if cmd <> glGetData then exit; for i := 0 to High(ConstTable) do if ConstTable[i].n = lab then begin Result := True; ret := ConstTable[i].d; end; end; function TAnsiCalculate.ExeLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; var i: Integer; begin if (glGetData = cmd) and Assigned(OnGetConst) then begin Result := OnGetConst(lab, ret); if Result then exit; end; Result := true; for i := 0 to High(Ext) do if Ext[i].ExeLabel(lab, ret, cmd) then exit; Result := True; case cmd of glSetData: begin for i := 0 to High(Labels) do if Labels[i].nm = lab then begin Labels[i].dt := ret; exit; end; i := length(labels); setlength(Labels, i + 1); Labels[i].nm := lab; Labels[i].dt := ret; exit; end; glGetData: begin for i := 0 to High(Labels) do if Labels[i].nm = lab then begin ret := Labels[i].dt; exit; end; Result := constLabel(lab, ret, cmd); exit; end; glPrePP: begin for i := 0 to High(Labels) do if Labels[i].nm = lab then begin Labels[i].dt := Labels[i].dt + ret; ret := Labels[i].dt; exit; end; //++/--の時は初期値が0の新規ラベルとして処理 i := length(labels); setlength(Labels, i + 1); Labels[i].nm := lab; Labels[i].dt := ret; exit; end; end; end; procedure TAnsiCalculate.putMsg(msg: AnsiString); var w, sz: integer; begin w := length(eMsg); sz := length(msg); SetLength(eMsg, w + sz); move(msg[1], eMsg[w + 1], sz); end; //FPCのUTF8の呪いから逃げるには文字列加算をしてはいけない procedure TAnsiCalculate.MsgOut(msg: AnsiString); var w, sz: integer; begin w := length(OutMsg); sz := length(msg); SetLength(OutMsg, w + sz); move(msg[1], OutMsg[w + 1], sz); end; procedure TAnsiCalculate.MsgOutLn(msg: AnsiString); var w, sz: integer; begin MsgOut(msg); MsgOut(#13#10); end; // CallParam:array of: Extended function TAnsiCalculate.CallFunc(const lab: AnsiString): boolean; var pmCnt, i: Integer; s: string; begin if Assigned(OnCallFunc) then begin Result := OnCallFunc(lab, CallParam); //外部関数がみつかるなら終了 if Result then exit; end; Result := true; for i := 0 to High(Ext) do if Ext[i].CallFunc(lab, CallParam) then exit; pmCnt := length(CallParam); num := 0; Result := true; if sameText(lab, 'pr') then begin if pmCnt = 0 then Err('pr(?)'); case pmCnt of 2: s := format(CallParam[0].nm, [CallParam[1].dt]); 3: s := format(CallParam[0].nm, [CallParam[1].dt, CallParam[2].dt]); 4: s := format(CallParam[0].nm, [CallParam[1].dt, CallParam[2].dt, CallParam[3].dt]); 5: s := format(CallParam[0].nm, [CallParam[1].dt, CallParam[2].dt, CallParam[3].dt, CallParam[4].dt]); else Err('pr("",... over)'); end; end; if pmCnt = 1 then begin if CallParam[0].nm <> '' then Err(lab + '(?)'); //文字列を渡されたエラー if sameText(lab, 'sin') then begin num := sin(CallParam[0].dt); exit; end; if sameText(lab, 'cos') then begin num := cos(CallParam[0].dt); exit; end; if sameText(lab, 'tan') then begin num := tan(CallParam[0].dt); exit; end; if sameText(lab, 'log') then begin num := ln(CallParam[0].dt); exit; end; if sameText(lab, 'ln') then begin num := ln(CallParam[0].dt); exit; end; if sameText(lab, 'exp') then begin num := exp(CallParam[0].dt); exit; end; if sameText(lab, 'FRAC') then begin num := FRAC(CallParam[0].dt); exit; end; if sameText(lab, 'ROUND') then begin num := ROUND(CallParam[0].dt); exit; end; if sameText(lab, 'TRUNC') then begin num := TRUNC(CallParam[0].dt); exit; end; if sameText(lab, 'ArcCos') then begin num := ArcCos(CallParam[0].dt); exit; end; if sameText(lab, 'ArcSin') then begin num := ArcSin(CallParam[0].dt); exit; end; if sameText(lab, 'coTan') then begin num := coTan(CallParam[0].dt); exit; end; if sameText(lab, 'Sinh') then begin num := Sinh(CallParam[0].dt); exit; end; if sameText(lab, 'Cosh') then begin num := Cosh(CallParam[0].dt); exit; end; if sameText(lab, 'Tanh') then begin num := Tanh(CallParam[0].dt); exit; end; if sameText(lab, 'ArcCosh') then begin num := ArcCosh(CallParam[0].dt); exit; end; if sameText(lab, 'ArcSinh') then begin num := ArcSinh(CallParam[0].dt); exit; end; if sameText(lab, 'ArcTanh') then begin num := ArcTanh(CallParam[0].dt); exit; end; if sameText(lab, 'LnXP1') then begin num := LnXP1(CallParam[0].dt); exit; end; if sameText(lab, 'Log10') then begin num := Log10(CallParam[0].dt); exit; end; if sameText(lab, 'Log2') then begin num := Log2(CallParam[0].dt); exit; end; if sameText(lab, 'ArcTanh') then begin num := ArcTanh(CallParam[0].dt); exit; end; Result := false; end; if pmCnt = 2 then begin if CallParam[0].nm <> '' then Err(lab + '(?,)'); //文字列を渡されたエラー if CallParam[1].nm <> '' then Err(lab + '(,?)'); //文字列を渡されたエラー if sameText(lab, 'ArcTan2') then begin num := ArcTan2(CallParam[0].dt, CallParam[1].dt); exit; end; if sameText(lab, 'Hypot') then begin num := Hypot(CallParam[0].dt, CallParam[1].dt); exit; end; if sameText(lab, 'LogN') then begin num := LogN(CallParam[0].dt, CallParam[1].dt); exit; end; if sameText(lab, 'Power') then begin num := Power(CallParam[0].dt, CallParam[1].dt); exit; end; Result := false; end; end; procedure TAnsiCalculate.AddTCalcuAddition(add: TCalcuAdditionClass); var i, sz: Integer; begin sz := length(Ext); for i := 0 to sz - 1 do if Ext[i].ClassName = add.ClassName then exit; //既に登録されていたら登録しない SetLength(Ext, sz + 1); Ext[sz] := add.Create; Ext[sz].owner := Self; end; function TAnsiCalculate.FileExec(const fname: AnsiString): boolean; var i: Integer; begin p := PAnsiChar(MyCmd); Result := false; for i := 0 to High(ext) do begin Result := Ext[i].FileExec(fname, p); if Result then exit; end; end; procedure CalcAddTCalcuAddition(add: TCalcuAdditionClass); var i, sz: Integer; begin sz := length(CalcuAdditions); for i := 0 to sz - 1 do if CalcuAdditions[i].ClassName = add.ClassName then exit; //既に登録されていたら登録しない SetLength(CalcuAdditions, sz + 1); CalcuAdditions[sz] := add; end; function TAnsiCalculate.EndCheck(p: PChar): boolean; begin endp := PChar(MyCmd) + length(MyCmd); Result := p >= endp; end; constructor TAnsiCalculate.Create(cmd: AnsiString); var i: Integer; begin setlength(ext, 0); OutFmt := ''; MyCmd := cmd; OutMsg := ''; SetLength(Labels, 0); for i := 0 to High(CalcuAdditions) do AddTCalcuAddition(CalcuAdditions[i]); end; destructor TAnsiCalculate.Destroy; var i, sz: Integer; begin sz := length(Ext); for i := 0 to sz - 1 do Ext[i].Free; SetLength(Ext, 0); inherited; end; { TCalcuAddition } function TCalcuAddition.CallFunc(const lab: AnsiString; Labels: TAMyCalLabel): boolean; begin Result := false; end; //継承しなかった時はラベルが無いとする function TCalcuAddition.ExeLabel(const lab: AnsiString; var ret: Extended; cmd: TGetLabelCmd): boolean; begin Result := false; end; function TCalcuAddition.FileExec(const fname: AnsiString; p: PChar): boolean; begin Result := false; end; function TCalcuAddition.LineCmd(const lab: AnsiString; var p: PChar): boolean; begin Result := false; end; procedure TCalcuAddition.StartEndScript(n: Integer); begin case n of //0:start 1:end; 0: begin end; 1: begin end; end; end; end.