using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.VisualBasic;
using NTERA.Core.Interop;
using NTERA.EmuEra.Game.EraEmu.Config;
using NTERA.EmuEra.Game.EraEmu.GameData.Expression;
using NTERA.EmuEra.Game.EraEmu.GameData.Variable;
using NTERA.EmuEra.Game.EraEmu.Sub;
using NTERA.EmuEra.Game.EraEmu._Library;
namespace NTERA.EmuEra.Game.EraEmu.GameData.Function
{
internal static partial class FunctionMethodCreator
{
#region CSVデータ関係
private sealed class GetcharaMethod : FunctionMethod
{
public GetcharaMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常2つ、1つ省略可能で1~2の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(Int64))
return name + "関数の1番目の引数の型が正しくありません";
//2は省略可能
if ((arguments.Length == 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 integer = arguments[0].GetIntValue(exm);
Int64 chara = -1L;
if (!Config.Config.CompatiSPChara)
{
//if ((arguments.Length > 1) && (arguments[1] != null) && (arguments[1].GetIntValue(exm) != 0))
return exm.VEvaluator.GetChara(integer);
}
//以下互換性用の旧処理
bool CheckSp = false;
if ((arguments.Length > 1) && (arguments[1] != null) && (arguments[1].GetIntValue(exm) != 0))
CheckSp = true;
if (CheckSp)
{
chara = exm.VEvaluator.GetChara_UseSp(integer, false);
if (chara != -1)
return chara;
return exm.VEvaluator.GetChara_UseSp(integer, true);
}
return exm.VEvaluator.GetChara_UseSp(integer, false);
}
}
private sealed class GetspcharaMethod : FunctionMethod
{
public GetspcharaMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
if(!Config.Config.CompatiSPChara)
throw new CodeEE("SPキャラ関係の機能は標準では使用できません(互換性オプション「SPキャラを使用する」をONにしてください)");
Int64 integer = arguments[0].GetIntValue(exm);
return exm.VEvaluator.GetChara_UseSp(integer, true);
}
}
private sealed class CsvStrDataMethod : FunctionMethod
{
CharacterStrData charaStr;
public CsvStrDataMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
charaStr = CharacterStrData.NAME;
CanRestructure = true;
}
public CsvStrDataMethod(CharacterStrData cStr)
{
ReturnType = typeof(string);
argumentTypeArray = null;
charaStr = cStr;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!arguments[0].IsInteger)
return name + "関数の1番目の引数が数値ではありません";
if (arguments.Length == 1)
return null;
if ((arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の変数が数値ではありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
long x = arguments[0].GetIntValue(exm);
long y = (arguments.Length > 1 && arguments[1] != null) ? arguments[1].GetIntValue(exm) : 0;
if (!Config.Config.CompatiSPChara && y != 0)
throw new CodeEE("SPキャラ関係の機能は標準では使用できません(互換性オプション「SPキャラを使用する」をONにしてください)");
return exm.VEvaluator.GetCharacterStrfromCSVData(x, charaStr, (y != 0), 0);
}
}
private sealed class CsvcstrMethod : FunctionMethod
{
public CsvcstrMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!arguments[0].IsInteger)
return name + "関数の1番目の引数が数値ではありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != typeof(Int64))
return name + "関数の2番目の変数が数値ではありません";
if (arguments.Length == 2)
return null;
if ((arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の変数が数値ではありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
long x = arguments[0].GetIntValue(exm);
long y = arguments[1].GetIntValue(exm);
long z = (arguments.Length == 3 && arguments[2] != null) ? arguments[2].GetIntValue(exm) : 0;
if(!Config.Config.CompatiSPChara && z != 0)
throw new CodeEE("SPキャラ関係の機能は標準では使用できません(互換性オプション「SPキャラを使用する」をONにしてください)");
return exm.VEvaluator.GetCharacterStrfromCSVData(x, CharacterStrData.CSTR, (z != 0), y);
}
}
private sealed class CsvDataMethod : FunctionMethod
{
CharacterIntData charaInt;
public CsvDataMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
charaInt = CharacterIntData.BASE;
CanRestructure = true;
}
public CsvDataMethod(CharacterIntData cInt)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
charaInt = cInt;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!arguments[0].IsInteger)
return name + "関数の1番目の引数が数値ではありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != typeof(Int64))
return name + "関数の2番目の変数が数値ではありません";
if (arguments.Length == 2)
return null;
if ((arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の変数が数値ではありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
long x = arguments[0].GetIntValue(exm);
long y = arguments[1].GetIntValue(exm);
long z = (arguments.Length == 3 && arguments[2] != null) ? arguments[2].GetIntValue(exm) : 0;
if(!Config.Config.CompatiSPChara && z != 0)
throw new CodeEE("SPキャラ関係の機能は標準では使用できません(互換性オプション「SPキャラを使用する」をONにしてください)");
return exm.VEvaluator.GetCharacterIntfromCSVData(x, charaInt, (z != 0), y);
}
}
private sealed class FindcharaMethod : FunctionMethod
{
public FindcharaMethod(bool last)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
isLast = last;
}
bool isLast;
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常3つ、1つ省略可能で2~3の引数が必要。
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 4)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数の型が正しくありません";
if (!(((VariableTerm)arguments[0]).Identifier.IsCharacterData))
return name + "関数の1番目の引数の変数がキャラクタ変数ではありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != arguments[0].GetOperandType())
return name + "関数の2番目の引数の型が正しくありません";
//3番目は省略可能
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
//4番目は省略可能
if ((arguments.Length >= 4) && (arguments[3] != null) && (arguments[3].GetOperandType() != typeof(Int64)))
return name + "関数の4番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
VariableTerm vTerm = (VariableTerm)arguments[0];
VariableToken varID = vTerm.Identifier;
Int64 elem = 0;
if (vTerm.Identifier.IsArray1D)
elem = vTerm.GetElementInt(1, exm);
else if (vTerm.Identifier.IsArray2D)
{
elem = vTerm.GetElementInt(1, exm) << 32;
elem += vTerm.GetElementInt(2, exm);
}
Int64 startindex = 0;
Int64 lastindex = exm.VEvaluator.CHARANUM;
if (arguments.Length >= 3 && arguments[2] != null)
startindex = arguments[2].GetIntValue(exm);
if (arguments.Length >= 4 && arguments[3] != null)
lastindex = arguments[3].GetIntValue(exm);
Int64 ret = -1;
if (startindex < 0 || startindex >= exm.VEvaluator.CHARANUM)
throw new CodeEE((isLast ? "" : "") + "関数の第3引数(" + startindex + ")はキャラクタ位置の範囲外です");
if (lastindex < 0 || lastindex > exm.VEvaluator.CHARANUM)
throw new CodeEE((isLast ? "" : "") + "関数の第4引数(" + lastindex + ")はキャラクタ位置の範囲外です");
if (varID.IsString)
{
string word = arguments[1].GetStrValue(exm);
ret = exm.VEvaluator.FindChara(varID, elem, word, startindex, lastindex, isLast);
}
else
{
Int64 word = arguments[1].GetIntValue(exm);
ret = exm.VEvaluator.FindChara(varID, elem, word, startindex, lastindex, isLast);
}
return (ret);
}
}
private sealed class ExistCsvMethod : FunctionMethod
{
public ExistCsvMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!arguments[0].IsInteger)
return name + "関数の1番目の引数が数値ではありません";
if (arguments.Length == 1)
return null;
if ((arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の変数が数値ではありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 no = arguments[0].GetIntValue(exm);
bool isSp =(arguments.Length == 2 && arguments[1] != null) ? (arguments[1].GetIntValue(exm) != 0) : false;
if(!Config.Config.CompatiSPChara && isSp)
throw new CodeEE("SPキャラ関係の機能は標準では使用できません(互換性オプション「SPキャラを使用する」をONにしてください)");
return (exm.VEvaluator.ExistCsv(no, isSp));
}
}
#endregion
#region 汎用処理系
private sealed class VarsizeMethod : FunctionMethod
{
public VarsizeMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = true;
//1808beta009 参照型変数の追加によりちょっと面倒になった
HasUniqueRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!arguments[0].IsString)
return name + "関数の1番目の引数が文字列ではありません";
if (arguments[0] is SingleTerm)
{
string varName = ((SingleTerm)arguments[0]).Str;
if (varName == "PARAM") ((SingleTerm)arguments[0]).Str = varName = "PALAM"; // JVN: Uses added setter to change PARAM to PALAM internally
if (GlobalStatic.IdentifierDictionary.GetVariableToken(varName, null, true) == null)
return name + "関数の1番目の引数が変数名ではありません";
}
if (arguments.Length == 1)
return null;
if ((arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の変数が数値ではありません";
if (arguments.Length == 2)
return null;
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
VariableToken var = GlobalStatic.IdentifierDictionary.GetVariableToken(arguments[0].GetStrValue(exm), null, true);
if (var == null)
throw new CodeEE("VARSIZEの1番目の引数(\"" + arguments[0].GetStrValue(exm) + "\")が変数名ではありません");
int dim = 0;
if (arguments.Length == 2 && arguments[1] != null)
dim = (int)arguments[1].GetIntValue(exm);
return (var.GetLength(dim));
}
public override bool UniqueRestructure(ExpressionMediator exm, IOperandTerm[] arguments)
{
arguments[0].Restructure(exm);
if (arguments.Length > 1)
arguments[1].Restructure(exm);
if (arguments[0] is SingleTerm && (arguments.Length == 1 || arguments[1] is SingleTerm))
{
VariableToken var = GlobalStatic.IdentifierDictionary.GetVariableToken(arguments[0].GetStrValue(exm), null, true);
if (var == null || var.IsReference)//可変長の場合は定数化できない
return false;
return true;
}
return false;
}
}
private sealed class CheckfontMethod : FunctionMethod
{
public CheckfontMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;//起動中に変わることもそうそうないはず……
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string str = arguments[0].GetStrValue(exm);
InstalledFontCollection ifc = new InstalledFontCollection();
Int64 isInstalled = 0;
foreach (FontFamily ff in ifc.Families)
{
if (ff.Name == str)
{
isInstalled = 1;
break;
}
}
return (isInstalled);
}
}
private sealed class CheckdataMethod : FunctionMethod
{
public CheckdataMethod(string name, EraSaveFileType type)
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = false;
this.name = name;
this.type = type;
}
string name;
EraSaveFileType type;
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 target = arguments[0].GetIntValue(exm);
if (target < 0)
throw new CodeEE(name + "の引数に負の値(" + target + ")が指定されました");
if (target > int.MaxValue)
throw new CodeEE(name + "の引数(" + target + ")が大きすぎます");
EraDataResult result = null;
result = exm.VEvaluator.CheckData((int)target, type);
exm.VEvaluator.RESULTS = result.DataMes;
return ((long)result.State);
}
}
///
/// ファイル名をstringで指定する版・CHKVARDATAとCHKCHARADATAはこっちに分類
///
private sealed class CheckdataStrMethod : FunctionMethod
{
public CheckdataStrMethod(string name, EraSaveFileType type)
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = false;
this.name = name;
this.type = type;
}
string name;
EraSaveFileType type;
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string datFilename = arguments[0].GetStrValue(exm);
EraDataResult result = null;
result = exm.VEvaluator.CheckData(datFilename, type);
exm.VEvaluator.RESULTS = result.DataMes;
return ((long)result.State);
}
}
///
/// ファイル探索関数
///
private sealed class FindFilesMethod : FunctionMethod
{
public FindFilesMethod(string name, EraSaveFileType type)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
this.name = name;
this.type = type;
}
string name;
EraSaveFileType type;
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length > 1)
return name + "関数の引数が多すぎます";
if (arguments.Length == 0 || arguments[0] == null)
return null;
if (!arguments[0].IsString)
return name + "関数の1番目の引数が文字列ではありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string pattern = "*";
if (arguments.Length > 0 && arguments[0] != null)
pattern = arguments[0].GetStrValue(exm);
List filepathes = null;
filepathes = exm.VEvaluator.GetDatFiles(type == EraSaveFileType.CharVar, pattern);
string[] results = exm.VEvaluator.VariableData.DataStringArray[(int)(VariableCode.RESULTS & VariableCode.__LOWERCASE__)];
if (filepathes.Count <= results.Length)
filepathes.CopyTo(results);
else
filepathes.CopyTo(0, results, 0, results.Length);
return filepathes.Count;
}
}
private sealed class IsSkipMethod : FunctionMethod
{
public IsSkipMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return exm.Process.SkipPrint ? 1L : 0L;
}
}
private sealed class MesSkipMethod : FunctionMethod
{
public MesSkipMethod(bool warn)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
this.warn = warn;
}
bool warn;
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length > 0)
return name + "関数の引数が多すぎます";
if (warn)
ParserMediator.Warn("関数MOUSESKIP()は推奨されません。代わりに関数MESSKIP()を使用してください", GlobalStatic.Process.GetScaningLine(), 1, false, false, null);
return null;
}
public override long GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return GlobalStatic.Console.MesSkip ? 1L : 0L;
}
}
private sealed class GetColorMethod : FunctionMethod
{
public GetColorMethod(bool isDef)
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = isDef;
defaultColor = isDef;
}
bool defaultColor;
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Color color = (defaultColor) ? Config.Config.ForeColor : GlobalStatic.Console.bgColor;
return (color.ToArgb() & 0xFFFFFF);
}
}
private sealed class GetFocusColorMethod : FunctionMethod
{
public GetFocusColorMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return (Config.Config.FocusColor.ToArgb() & 0xFFFFFF);
}
}
private sealed class GetBGColorMethod : FunctionMethod
{
public GetBGColorMethod(bool isDef)
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = isDef;
defaultColor = isDef;
}
bool defaultColor;
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Color color = (defaultColor) ? Config.Config.BackColor : GlobalStatic.Console.bgColor;
return (color.ToArgb() & 0xFFFFFF);
}
}
private sealed class GetStyleMethod : FunctionMethod
{
public GetStyleMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
FontStyle fontstyle = FontStyle.Regular;//GlobalStatic.Console.StringStyle.FontStyle;
long ret = 0;
if ((fontstyle & FontStyle.Bold) == FontStyle.Bold)
ret |= 1;
if ((fontstyle & FontStyle.Italic) == FontStyle.Italic)
ret |= 2;
if ((fontstyle & FontStyle.Strikeout) == FontStyle.Strikeout)
ret |= 4;
if ((fontstyle & FontStyle.Underline) == FontStyle.Underline)
ret |= 8;
return (ret);
}
}
private sealed class GetFontMethod : FunctionMethod
{
public GetFontMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
return "MS Gothic"; // (GlobalStatic.Console.StringStyle.Fontname);
}
}
private sealed class BarStringMethod : FunctionMethod
{
public BarStringMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(long), typeof(long), typeof(long) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
long var = arguments[0].GetIntValue(exm);
long max = arguments[1].GetIntValue(exm);
long length = arguments[2].GetIntValue(exm);
return exm.CreateBar(var, max, length);
}
}
private sealed class CurrentAlignMethod : FunctionMethod
{
public CurrentAlignMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
if (exm.Console.Alignment == DisplayLineAlignment.LEFT)
return "LEFT";
if (exm.Console.Alignment == DisplayLineAlignment.CENTER)
return "CENTER";
return "RIGHT";
}
}
private sealed class CurrentRedrawMethod : FunctionMethod
{
public CurrentRedrawMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override long GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return (exm.Console.Redraw == ConsoleRedraw.None) ? 0L : 1L;
}
}
private sealed class ColorFromNameMethod : FunctionMethod
{
public ColorFromNameMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override long GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string colorName = arguments[0].GetStrValue(exm);
Color color = Color.FromName(colorName);
int i = 0;
if (color.A > 0)
i = (color.R << 16) + (color.G << 8) + color.B;
else
{
if (colorName.Equals("transparent", StringComparison.OrdinalIgnoreCase))
throw new CodeEE("無色透明(Transparent)は色として指定できません");
//throw new CodeEE("指定された色名\"" + colorName + "\"は無効な色名です");
i = -1;
}
return i;
}
}
private sealed class ColorFromRGBMethod : FunctionMethod
{
public ColorFromRGBMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(long), typeof(long), typeof(long) };
CanRestructure = true;
}
public override long GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
long r = arguments[0].GetIntValue(exm);
if(r < 0 || r > 255)
throw new CodeEE("第1引数が0から255の範囲外です");
long g = arguments[1].GetIntValue(exm);
if(g< 0 || g > 255)
throw new CodeEE("第2引数が0から255の範囲外です");
long b = arguments[2].GetIntValue(exm);
if(b < 0 || b > 255)
throw new CodeEE("第3引数が0から255の範囲外です");
return (r << 16) + (g << 8) + b;
}
}
///
/// 1810 作ったけど保留
///
private sealed class GetRefMethod : FunctionMethod
{
public GetRefMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 1)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is UserDefinedRefMethodNoArgTerm))
return name + "関数の1番目の引数が関数参照ではありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
return ((UserDefinedRefMethodNoArgTerm)arguments[0]).GetRefName();
}
}
#endregion
#region 定数取得
private sealed class MoneyStrMethod : FunctionMethod
{
public MoneyStrMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常2つ、1つ省略可能で1~2の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(Int64))
return name + "関数の1番目の引数の型が正しくありません";
if ((arguments.Length >= 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(string)))
return name + "関数の2番目の引数の型が正しくありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
long money = arguments[0].GetIntValue(exm);
if ((arguments.Length < 2) || (arguments[1] == null))
return (Config.Config.MoneyFirst) ? Config.Config.MoneyLabel + money : money + Config.Config.MoneyLabel;
string format = arguments[1].GetStrValue(exm);
string ret;
try
{
ret = money.ToString(format);
}
catch (FormatException)
{
throw new CodeEE("MONEYSTR関数の第2引数の書式指定が間違っています");
}
return (Config.Config.MoneyFirst) ? Config.Config.MoneyLabel + ret : ret + Config.Config.MoneyLabel;
}
}
private sealed class GetPrintCPerLineMethod : FunctionMethod
{
public GetPrintCPerLineMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return (Config.Config.PrintCPerLine);
}
}
private sealed class PrintCLengthMethod : FunctionMethod
{
public PrintCLengthMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = true;
}
public override long GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return (Config.Config.PrintCLength);
}
}
private sealed class GetSaveNosMethod : FunctionMethod
{
public GetSaveNosMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return (Config.Config.SaveDataNos);
}
}
private sealed class GettimeMethod : FunctionMethod
{
public GettimeMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
long date = DateTime.Now.Year;
date = date * 100 + DateTime.Now.Month;
date = date * 100 + DateTime.Now.Day;
date = date * 100 + DateTime.Now.Hour;
date = date * 100 + DateTime.Now.Minute;
date = date * 100 + DateTime.Now.Second;
date = date * 1000 + DateTime.Now.Millisecond;
return (date);//17桁。2京くらい。
}
}
private sealed class GettimesMethod : FunctionMethod
{
public GettimesMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
return (DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"));
}
}
private sealed class GetmsMethod : FunctionMethod
{
public GetmsMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
//西暦0001年1月1日からの経過時間をミリ秒で。
//Ticksは100ナノ秒単位であるが実際にはそんな精度はないので無駄。
return (DateTime.Now.Ticks / 10000);
}
}
private sealed class GetSecondMethod : FunctionMethod
{
public GetSecondMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
//西暦0001年1月1日からの経過時間を秒で。
//Ticksは100ナノ秒単位であるが実際にはそんな精度はないので無駄。
return (DateTime.Now.Ticks / 10000000);
}
}
#endregion
#region 数学関数
private sealed class RandMethod : FunctionMethod
{
public RandMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常2つ、1つ省略可能で1~2の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments.Length == 1)
{
if (arguments[0] == null)
return name + "関数には少なくとも1つの引数が必要です";
if ((arguments[0].GetOperandType() != typeof(Int64)))
return name + "関数の1番目の引数の型が正しくありません";
return null;
}
//1番目は省略可能
if ((arguments[0] != null) && (arguments[0].GetOperandType() != typeof(Int64)))
return name + "関数の1番目の引数の型が正しくありません";
if ((arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 max = 0;
Int64 min = 0;
if (arguments.Length == 1)
max = arguments[0].GetIntValue(exm);
else
{
if (arguments[0] != null)
min = arguments[0].GetIntValue(exm);
max = arguments[1].GetIntValue(exm);
}
if (max <= min)
{
if (min == 0)
throw new CodeEE("RANDの最大値に0以下の値(" + max + ")が指定されました");
throw new CodeEE("RANDの最大値に最小値以下の値(" + max + ")が指定されました");
}
return (exm.VEvaluator.GetNextRand(max - min) + min);
}
}
private sealed class MaxMethod : FunctionMethod
{
bool isMax;
public MaxMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isMax = true;
CanRestructure = true;
}
public MaxMethod(bool max)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isMax = max;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
for (int i = 0; i < arguments.Length; i++)
{
if (arguments[i] == null)
return name + "関数の" + (i + 1) + "番目の引数は省略できません";
if (arguments[i].GetOperandType() != typeof(Int64))
return name + "関数の" + (i + 1) + "番目の引数の型が正しくありません";
}
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
Int64 newRet = arguments[i].GetIntValue(exm);
if (isMax)
{
if (ret < newRet)
ret = newRet;
}
else
{
if (ret > newRet)
ret = newRet;
}
}
return (ret);
}
}
private sealed class AbsMethod : FunctionMethod
{
public AbsMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
return (Math.Abs(ret));
}
}
private sealed class PowerMethod : FunctionMethod
{
public PowerMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 x = arguments[0].GetIntValue(exm);
Int64 y = arguments[1].GetIntValue(exm);
double pow = Math.Pow(x, y);
if (double.IsNaN(pow))
throw new CodeEE("累乗結果が非数値です");
if (double.IsInfinity(pow))
throw new CodeEE("累乗結果が無限大です");
if ((pow >= Int64.MaxValue) || (pow <= Int64.MinValue))
throw new CodeEE("累乗結果(" + pow + ")が64ビット符号付き整数の範囲外です");
return ((long)pow);
}
}
private sealed class SqrtMethod : FunctionMethod
{
public SqrtMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
if (ret < 0)
throw new CodeEE("SQRT関数の引数に負の値が指定されました");
return ((Int64)Math.Sqrt(ret));
}
}
private sealed class CbrtMethod : FunctionMethod
{
public CbrtMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
if (ret < 0)
throw new CodeEE("CBRT関数の引数に負の値が指定されました");
return ((Int64)Math.Pow(ret, 1.0 / 3.0));
}
}
private sealed class LogMethod : FunctionMethod
{
double Base;
public LogMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
Base = Math.E;
CanRestructure = true;
}
public LogMethod(double b)
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
Base = b;
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
if (ret <= 0)
throw new CodeEE("対数関数の引数に0以下の値が指定されました");
if (Base <= 0.0d)
throw new CodeEE("対数関数の底に0以下の値が指定されました");
double dret = ret;
if (Base == Math.E)
dret = Math.Log(dret);
else
dret = Math.Log10(dret);
if (double.IsNaN(dret))
throw new CodeEE("計算値が非数値です");
if (double.IsInfinity(dret))
throw new CodeEE("計算値が無限大です");
if ((dret >= Int64.MaxValue) || (dret <= Int64.MinValue))
throw new CodeEE("計算結果(" + dret + ")が64ビット符号付き整数の範囲外です");
return ((Int64)dret);
}
}
private sealed class ExpMethod : FunctionMethod
{
public ExpMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
double dret = Math.Exp(ret);
if (double.IsNaN(dret))
throw new CodeEE("計算値が非数値です");
if (double.IsInfinity(dret))
throw new CodeEE("計算値が無限大です");
if ((dret >= Int64.MaxValue) || (dret <= Int64.MinValue))
throw new CodeEE("計算結果(" + dret + ")が64ビット符号付き整数の範囲外です");
return ((Int64)dret);
}
}
private sealed class SignMethod : FunctionMethod
{
public SignMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = arguments[0].GetIntValue(exm);
return (Math.Sign(ret));
}
}
private sealed class GetLimitMethod : FunctionMethod
{
public GetLimitMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64), typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 value = arguments[0].GetIntValue(exm);
Int64 min = arguments[1].GetIntValue(exm);
Int64 max = arguments[2].GetIntValue(exm);
Int64 ret = 0;
if (value < min)
ret = min;
else if (value > max)
ret = max;
else
ret = value;
return (ret);
}
}
#endregion
#region 変数操作系
private sealed class SumArrayMethod : FunctionMethod
{
bool isCharaRange;
public SumArrayMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = false;
CanRestructure = false;
}
public SumArrayMethod(bool isChara)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = isChara;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数が変数ではありません";
VariableTerm varToken = (VariableTerm)arguments[0];
if (varToken.IsString)
return name + "関数の1番目の引数が数値変数ではありません";
if (isCharaRange && !varToken.Identifier.IsCharacterData)
return name + "関数の1番目の引数がキャラクタ変数ではありません";
if (!isCharaRange && !varToken.Identifier.IsArray1D && !varToken.Identifier.IsArray2D && !varToken.Identifier.IsArray3D)
return name + "関数の1番目の引数が配列変数ではありません";
if (arguments.Length == 1)
return null;
if ((arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の変数が数値ではありません";
if (arguments.Length == 2)
return null;
if ((arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の変数が数値ではありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
VariableTerm varTerm = (VariableTerm)arguments[0];
Int64 index1 = (arguments.Length >= 2 && arguments[1] != null) ? arguments[1].GetIntValue(exm) : 0;
Int64 index2 = (arguments.Length == 3 && arguments[2] != null) ? arguments[2].GetIntValue(exm) : (isCharaRange ? exm.VEvaluator.CHARANUM : varTerm.GetLastLength());
FixedVariableTerm p = varTerm.GetFixedVariableTerm(exm);
if (!isCharaRange)
{
p.IsArrayRangeValid(index1, index2, "SUMARRAY", 2L, 3L);
return (exm.VEvaluator.GetArraySum(p, index1, index2));
}
Int64 charaNum = exm.VEvaluator.CHARANUM;
if (index1 >= charaNum || index1 < 0 || index2 > charaNum || index2 < 0)
throw new CodeEE("SUMCARRAY関数の範囲指定がキャラクタ配列の範囲を超えています(" + index1 + "~" + index2 + ")");
return (exm.VEvaluator.GetArraySumChara(p, index1, index2));
}
}
private sealed class MatchMethod : FunctionMethod
{
bool isCharaRange;
public MatchMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = false;
CanRestructure = false;
HasUniqueRestructure = true;
}
public MatchMethod(bool isChara)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = isChara;
CanRestructure = false;
HasUniqueRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 4)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数が変数ではありません";
VariableTerm varToken = (VariableTerm)arguments[0];
if (isCharaRange && !varToken.Identifier.IsCharacterData)
return name + "関数の1番目の引数がキャラクタ変数ではありません";
if (!isCharaRange && (varToken.Identifier.IsArray2D || varToken.Identifier.IsArray3D))
return name + "関数は二重配列・三重配列には対応していません";
if (!isCharaRange && !varToken.Identifier.IsArray1D)
return name + "関数の1番目の引数が配列変数ではありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != arguments[0].GetOperandType())
return name + "関数の1番目の引数と2番目の引数の型が異なります";
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
if ((arguments.Length >= 4) && (arguments[3] != null) && (arguments[3].GetOperandType() != typeof(Int64)))
return name + "関数の4番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
VariableTerm varTerm = arguments[0] as VariableTerm;
Int64 start = (arguments.Length > 2 && arguments[2] != null) ? arguments[2].GetIntValue(exm) : 0;
Int64 end = (arguments.Length > 3 && arguments[3] != null) ? arguments[3].GetIntValue(exm) : (isCharaRange ? exm.VEvaluator.CHARANUM : varTerm.GetLength());
FixedVariableTerm p = varTerm.GetFixedVariableTerm(exm);
if (!isCharaRange)
{
p.IsArrayRangeValid(start, end, "MATCH", 3L, 4L);
if (arguments[0].GetOperandType() == typeof(Int64))
{
Int64 targetValue = arguments[1].GetIntValue(exm);
return (exm.VEvaluator.GetMatch(p, targetValue, start, end));
}
string targetStr = arguments[1].GetStrValue(exm);
return (exm.VEvaluator.GetMatch(p, targetStr, start, end));
}
Int64 charaNum = exm.VEvaluator.CHARANUM;
if (start >= charaNum || start < 0 || end > charaNum || end < 0)
throw new CodeEE("CMATCH関数の範囲指定がキャラクタ配列の範囲を超えています(" + start + "~" + end + ")");
if (arguments[0].GetOperandType() == typeof(Int64))
{
Int64 targetValue = arguments[1].GetIntValue(exm);
return (exm.VEvaluator.GetMatchChara(p, targetValue, start, end));
}
{
string targetStr = arguments[1].GetStrValue(exm);
return (exm.VEvaluator.GetMatchChara(p, targetStr, start, end));
}
}
public override bool UniqueRestructure(ExpressionMediator exm, IOperandTerm[] arguments)
{
arguments[0].Restructure(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (arguments[i] == null)
continue;
arguments[i] = arguments[i].Restructure(exm);
}
return false;
}
}
private sealed class GroupMatchMethod : FunctionMethod
{
public GroupMatchMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
Type baseType = arguments[0].GetOperandType();
for (int i = 1; i < arguments.Length; i++)
{
if (arguments[i] == null)
return name + "関数の" + (i + 1) + "番目の引数は省略できません";
if (arguments[i].GetOperandType() != baseType)
return name + "関数の" + (i + 1) + "番目の引数の型が正しくありません";
}
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 ret = 0;
if (arguments[0].GetOperandType() == typeof(Int64))
{
Int64 baseValue = arguments[0].GetIntValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (baseValue == arguments[i].GetIntValue(exm))
ret += 1;
}
}
else
{
string baseString = arguments[0].GetStrValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (baseString == arguments[i].GetStrValue(exm))
ret += 1;
}
}
return (ret);
}
}
private sealed class NosamesMethod : FunctionMethod
{
public NosamesMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
Type baseType = arguments[0].GetOperandType();
for (int i = 1; i < arguments.Length; i++)
{
if (arguments[i] == null)
return name + "関数の" + (i + 1) + "番目の引数は省略できません";
if (arguments[i].GetOperandType() != baseType)
return name + "関数の" + (i + 1) + "番目の引数の型が正しくありません";
}
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
if (arguments[0].GetOperandType() == typeof(Int64))
{
Int64 baseValue = arguments[0].GetIntValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (baseValue == arguments[i].GetIntValue(exm))
return 0L;
}
}
else
{
string baseValue = arguments[0].GetStrValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (baseValue == arguments[i].GetStrValue(exm))
return 0L;
}
}
return 1L;
}
}
private sealed class AllsamesMethod : FunctionMethod
{
public AllsamesMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
Type baseType = arguments[0].GetOperandType();
for (int i = 1; i < arguments.Length; i++)
{
if (arguments[i] == null)
return name + "関数の" + (i + 1) + "番目の引数は省略できません";
if (arguments[i].GetOperandType() != baseType)
return name + "関数の" + (i + 1) + "番目の引数の型が正しくありません";
}
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
if (arguments[0].GetOperandType() == typeof(Int64))
{
Int64 baseValue = arguments[0].GetIntValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (baseValue != arguments[i].GetIntValue(exm))
return 0L;
}
}
else
{
string baseValue = arguments[0].GetStrValue(exm);
for (int i = 1; i < arguments.Length; i++)
{
if (baseValue != arguments[i].GetStrValue(exm))
return 0L;
}
}
return 1L;
}
}
private sealed class MaxArrayMethod : FunctionMethod
{
bool isCharaRange;
bool isMax;
string funcName;
public MaxArrayMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = false;
isMax = true;
funcName = "MAXARRAY";
CanRestructure = false;
}
public MaxArrayMethod(bool isChara)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = isChara;
isMax = true;
if (isCharaRange)
funcName = "MAXCARRAY";
else
funcName = "MAXARRAY";
CanRestructure = false;
}
public MaxArrayMethod(bool isChara, bool isMaxFunc)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = isChara;
isMax = isMaxFunc;
funcName = (isMax ? "MAX" : "MIN") + (isCharaRange ? "C" : "") + "ARRAY";
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数が変数ではありません";
VariableTerm varToken = (VariableTerm)arguments[0];
if (isCharaRange && !varToken.Identifier.IsCharacterData)
return name + "関数の1番目の引数がキャラクタ変数ではありません";
if (!varToken.IsInteger)
return name + "関数の1番目の引数が数値変数ではありません";
if (!isCharaRange && (varToken.Identifier.IsArray2D || varToken.Identifier.IsArray3D))
return name + "関数は二重配列・三重配列には対応していません";
if (!varToken.Identifier.IsArray1D)
return name + "関数の1番目の引数が配列変数ではありません";
if ((arguments.Length >= 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の引数の型が正しくありません";
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
VariableTerm vTerm = (VariableTerm)arguments[0];
Int64 start = (arguments.Length > 1 && arguments[1] != null) ? arguments[1].GetIntValue(exm) : 0;
Int64 end = (arguments.Length > 2 && arguments[2] != null) ? end = arguments[2].GetIntValue(exm) : (isCharaRange ? exm.VEvaluator.CHARANUM : vTerm.GetLength());
FixedVariableTerm p = vTerm.GetFixedVariableTerm(exm);
if (!isCharaRange)
{
p.IsArrayRangeValid(start, end, funcName, 2L, 3L);
return (exm.VEvaluator.GetMaxArray(p, start, end, isMax));
}
Int64 charaNum = exm.VEvaluator.CHARANUM;
if (start >= charaNum || start < 0 || end > charaNum || end < 0)
throw new CodeEE(funcName + "関数の範囲指定がキャラクタ配列の範囲を超えています(" + start + "~" + end + ")");
return (exm.VEvaluator.GetMaxArrayChara(p, start, end, isMax));
}
}
private sealed class GetbitMethod : FunctionMethod
{
public GetbitMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64) };
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
string ret = base.CheckArgumentType(name, arguments);
if (ret != null)
return ret;
if (arguments[1] is SingleTerm)
{
Int64 m = ((SingleTerm)arguments[1]).Int;
if (m < 0 || m > 63)
return "GETBIT関数の第2引数(" + m + ")が範囲(0~63)を超えています";
}
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 n = arguments[0].GetIntValue(exm);
Int64 m = arguments[1].GetIntValue(exm);
if ((m < 0) || (m > 63))
throw new CodeEE("GETBIT関数の第2引数(" + m + ")が範囲(0~63)を超えています");
int mi = (int)m;
return ((n >> mi) & 1);
}
}
private sealed class GetnumMethod : FunctionMethod
{
public GetnumMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = true;
HasUniqueRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length != 2)
return name + "関数には2つの引数が必要です";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数の型が正しくありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != typeof(string))
return name + "関数の2番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
VariableTerm vToken = (VariableTerm)arguments[0];
VariableCode varCode = vToken.Identifier.Code;
string key = arguments[1].GetStrValue(exm);
int ret = 0;
if (exm.VEvaluator.Constant.TryKeywordToInteger(out ret, varCode, key, -1))
return ret;
return -1;
}
public override bool UniqueRestructure(ExpressionMediator exm, IOperandTerm[] arguments)
{
arguments[1] = arguments[1].Restructure(exm);
return arguments[1] is SingleTerm;
}
}
private sealed class GetPalamLVMethod : FunctionMethod
{
public GetPalamLVMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64) };
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
string errStr = base.CheckArgumentType(name, arguments);
if (errStr != null)
return errStr;
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 value = arguments[0].GetIntValue(exm);
Int64 maxLv = arguments[1].GetIntValue(exm);
return (exm.VEvaluator.getPalamLv(value, maxLv));
}
}
private sealed class GetExpLVMethod : FunctionMethod
{
public GetExpLVMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64) };
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
string errStr = base.CheckArgumentType(name, arguments);
if (errStr != null)
return errStr;
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 value = arguments[0].GetIntValue(exm);
Int64 maxLv = arguments[1].GetIntValue(exm);
return (exm.VEvaluator.getExpLv(value, maxLv));
}
}
private sealed class FindElementMethod : FunctionMethod
{
public FindElementMethod(bool last)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = true; //すべて定数項ならできるはず
HasUniqueRestructure = true;
isLast = last;
funcName = isLast ? "FINDLASTELEMENT" : "FINDELEMENT";
}
bool isLast;
string funcName;
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 5)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
VariableTerm varToken = arguments[0] as VariableTerm;
if (varToken == null)
return name + "関数の1番目の引数が変数ではありません";
if (varToken.Identifier.IsArray2D || varToken.Identifier.IsArray3D)
return name + "関数は二重配列・三重配列には対応していません";
if (!varToken.Identifier.IsArray1D)
return name + "関数の1番目の引数が配列変数ではありません";
Type baseType = arguments[0].GetOperandType();
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != baseType)
return name + "関数の2番目の引数の型が正しくありません";
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
if ((arguments.Length >= 4) && (arguments[3] != null) && (arguments[3].GetOperandType() != typeof(Int64)))
return name + "関数の4番目の引数の型が正しくありません";
if ((arguments.Length >= 5) && (arguments[4] != null) && (arguments[4].GetOperandType() != typeof(Int64)))
return name + "関数の5番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
bool isExact = false;
VariableTerm varTerm = (VariableTerm)arguments[0];
Int64 start = (arguments.Length > 2 && arguments[2] != null) ? arguments[2].GetIntValue(exm) : 0;
Int64 end = (arguments.Length > 3 && arguments[3] != null) ? arguments[3].GetIntValue(exm) : varTerm.GetLength();
if (arguments.Length > 4 && arguments[4] != null)
isExact = (arguments[4].GetIntValue(exm) != 0);
FixedVariableTerm p = varTerm.GetFixedVariableTerm(exm);
p.IsArrayRangeValid(start, end, funcName, 3L, 4L);
if (arguments[0].GetOperandType() == typeof(Int64))
{
Int64 targetValue = arguments[1].GetIntValue(exm);
return exm.VEvaluator.FindElement(p, targetValue, start, end, isExact, isLast);
}
Regex targetString = null;
try
{
targetString = new Regex(arguments[1].GetStrValue(exm));
}
catch (ArgumentException)
{
throw new CodeEE("第2引数が正規表現として不正です");
}
return exm.VEvaluator.FindElement(p, targetString, start, end, isExact, isLast);
}
public override bool UniqueRestructure(ExpressionMediator exm, IOperandTerm[] arguments)
{
bool isConst = true;
arguments[0].Restructure(exm);
VariableTerm varToken = arguments[0] as VariableTerm;
isConst = varToken.Identifier.IsConst;
for (int i = 1; i < arguments.Length; i++)
{
if (arguments[i] == null)
continue;
arguments[i] = arguments[i].Restructure(exm);
if (isConst && !(arguments[i] is SingleTerm))
isConst = false;
}
return isConst;
}
}
private sealed class InRangeMethod : FunctionMethod
{
public InRangeMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64), typeof(Int64) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 value = arguments[0].GetIntValue(exm);
Int64 min = arguments[1].GetIntValue(exm);
Int64 max = arguments[2].GetIntValue(exm);
return ((value >= min) && (value <= max)) ? 1L : 0L;
}
}
private sealed class InRangeArrayMethod : FunctionMethod
{
public InRangeArrayMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = false;
}
public InRangeArrayMethod(bool isChara)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
isCharaRange = isChara;
CanRestructure = false;
}
private bool isCharaRange;
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 6)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数が変数ではありません";
VariableTerm varToken = (VariableTerm)arguments[0];
if (isCharaRange && !varToken.Identifier.IsCharacterData)
return name + "関数の1番目の引数がキャラクタ変数ではありません";
if (!isCharaRange && (varToken.Identifier.IsArray2D || varToken.Identifier.IsArray3D))
return name + "関数は二重配列・三重配列には対応していません";
if (!isCharaRange && !varToken.Identifier.IsArray1D)
return name + "関数の1番目の引数が配列変数ではありません";
if (!varToken.IsInteger)
return name + "関数の1番目の引数が数値型変数ではありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != typeof(Int64))
return name + "関数の2番目の引数が数値型ではありません";
if (arguments[2] == null)
return name + "関数の3番目の引数は省略できません";
if (arguments[2].GetOperandType() != typeof(Int64))
return name + "関数の3番目の引数が数値型ではありません";
if ((arguments.Length >= 4) && (arguments[3] != null) && (arguments[3].GetOperandType() != typeof(Int64)))
return name + "関数の4番目の引数の型が正しくありません";
if ((arguments.Length >= 5) && (arguments[4] != null) && (arguments[4].GetOperandType() != typeof(Int64)))
return name + "関数の5番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Int64 min = arguments[1].GetIntValue(exm);
Int64 max = arguments[2].GetIntValue(exm);
VariableTerm varTerm = arguments[0] as VariableTerm;
Int64 start = (arguments.Length > 3 && arguments[3] != null) ? arguments[3].GetIntValue(exm) : 0;
Int64 end = (arguments.Length > 4 && arguments[4] != null) ? arguments[4].GetIntValue(exm) : (isCharaRange ? exm.VEvaluator.CHARANUM : varTerm.GetLength());
FixedVariableTerm p = varTerm.GetFixedVariableTerm(exm);
if (!isCharaRange)
{
p.IsArrayRangeValid(start, end, "INRANGEARRAY", 4L, 5L);
return (exm.VEvaluator.GetInRangeArray(p, min, max, start, end));
}
Int64 charaNum = exm.VEvaluator.CHARANUM;
if (start >= charaNum || start < 0 || end > charaNum || end < 0)
throw new CodeEE("INRANGECARRAY関数の範囲指定がキャラクタ配列の範囲を超えています(" + start + "~" + end + ")");
return (exm.VEvaluator.GetInRangeArrayChara(p, min, max, start, end));
}
}
#endregion
#region 文字列操作系
private sealed class StrlenMethod : FunctionMethod
{
public StrlenMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string str = arguments[0].GetStrValue(exm, true); // JVN: Return TR string's length when necessary
str = Translation.translate(str, "ALL", true); //Bartoum : Check if it's not present in all (Ex: Names in gvt for Pedo)
//Translation.isStrlens = false;
return (LangManager.GetStrlenLang(str));
}
}
private sealed class StrlenuMethod : FunctionMethod
{
public StrlenuMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string str = arguments[0].GetStrValue(exm, true); // JVN: Return TR string's length when necessary
str = Translation.translate(str, "ALL", true); //Bartoum : Check if it's not present in all (Ex: Names in gvt for Pedo)
return (str.Length);
}
}
private sealed class SubstringMethod : FunctionMethod
{
public SubstringMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常3つ、2つ省略可能で1~3の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(string))
return name + "関数の1番目の引数の型が正しくありません";
//2、3は省略可能
if ((arguments.Length >= 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の引数の型が正しくありません";
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string str = arguments[0].GetStrValue(exm);
int start = 0;
int length = -1;
if ((arguments.Length >= 2) && (arguments[1] != null))
start = (int)arguments[1].GetIntValue(exm);
if ((arguments.Length >= 3) && (arguments[2] != null))
length = (int)arguments[2].GetIntValue(exm);
return (LangManager.GetSubStringLang(str, start, length));
}
}
private sealed class SubstringuMethod : FunctionMethod
{
public SubstringuMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常3つ、2つ省略可能で1~3の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(string))
return name + "関数の1番目の引数の型が正しくありません";
//2、3は省略可能
if ((arguments.Length >= 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の引数の型が正しくありません";
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string str = arguments[0].GetStrValue(exm);
int start = 0;
int length = -1;
if ((arguments.Length >= 2) && (arguments[1] != null))
start = (int)arguments[1].GetIntValue(exm);
if ((arguments.Length >= 3) && (arguments[2] != null))
length = (int)arguments[2].GetIntValue(exm);
if ((start >= str.Length) || (length == 0))
return ("");
if ((length < 0) || (length > str.Length))
length = str.Length;
if (start <= 0)
{
if (length == str.Length)
return (str);
start = 0;
}
if ((start + length) > str.Length)
length = str.Length - start;
return (str.Substring(start, length));
}
}
private sealed class StrfindMethod : FunctionMethod
{
public StrfindMethod(bool unicode)
{
ReturnType = typeof(Int64);
argumentTypeArray = null;
CanRestructure = true;
this.unicode = unicode;
}
bool unicode;
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常3つ、1つ省略可能で2~3の引数が必要。
if (arguments.Length < 2)
return name + "関数には少なくとも2つの引数が必要です";
if (arguments.Length > 3)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(string))
return name + "関数の1番目の引数の型が正しくありません";
if (arguments[1] == null)
return name + "関数の2番目の引数は省略できません";
if (arguments[1].GetOperandType() != typeof(string))
return name + "関数の2番目の引数の型が正しくありません";
//3つ目は省略可能
if ((arguments.Length >= 3) && (arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string target = arguments[0].GetStrValue(exm);
string word = arguments[1].GetStrValue(exm);
int JISstart = 0, UFTstart = 0;
if ((arguments.Length >= 3) && (arguments[2] != null))
{
if (unicode)
{
UFTstart = (int)arguments[2].GetIntValue(exm);
}
else
{
JISstart = (int)arguments[2].GetIntValue(exm);
UFTstart = LangManager.GetUFTIndex(target, JISstart);
}
}
if (UFTstart < 0 || UFTstart >= target.Length)
return (-1);
int index = target.IndexOf(word, UFTstart);
if (index > 0 && !unicode)
{
string subStr = target.Substring(0, index);
index = LangManager.GetStrlenLang(subStr);
}
return (index);
}
}
private sealed class StrCountMethod : FunctionMethod
{
public StrCountMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string), typeof(string) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
Regex reg = null;
try
{
reg = new Regex(arguments[1].GetStrValue(exm));
}
catch (ArgumentException e)
{
throw new CodeEE("第2引数が正規表現として不正です:" + e.Message);
}
return (reg.Matches(arguments[0].GetStrValue(exm)).Count);
}
}
private sealed class ToStrMethod : FunctionMethod
{
public ToStrMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常2つ、1つ省略可能で1~2の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(Int64))
return name + "関数の1番目の引数の型が正しくありません";
if ((arguments.Length >= 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(string)))
return name + "関数の2番目の引数の型が正しくありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
Int64 i = arguments[0].GetIntValue(exm);
if ((arguments.Length < 2) || (arguments[1] == null))
return (i.ToString());
string format = arguments[1].GetStrValue(exm);
string ret;
try
{
ret = i.ToString(format);
}
catch (FormatException)
{
throw new CodeEE("TOSTR関数の書式指定が間違っています");
}
return (ret);
}
}
private sealed class ToIntMethod : FunctionMethod
{
public ToIntMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string str = arguments[0].GetStrValue(exm);
if (str == null || str == "")
return (0);
//全角文字が入ってるなら無条件で0を返す
if (str.Length < LangManager.GetStrlenLang(str))
return (0);
StringStream st = new StringStream(str);
if (!char.IsDigit(st.Current) && st.Current != '+' && st.Current != '-')
return (0);
if ((st.Current == '+' || st.Current == '-') && !char.IsDigit(st.Next))
return (0);
Int64 ret = LexicalAnalyzer.ReadInt64(st, true);
if (!st.EOS)
{
if (st.Current == '.')
{
st.ShiftNext();
while (!st.EOS)
{
if (!char.IsDigit(st.Current))
return (0);
st.ShiftNext();
}
}
else
return (0);
}
return ret;
}
}
//難読化用属性。enum.ToString()やenum.Parse()を行うなら(Exclude=true)にすること。
[Obfuscation(Exclude = false)]
//TOUPPER等の処理を汎用化するためのenum
enum StrFormType
{
Upper = 0,
Lower = 1,
Half = 2,
Full = 3
}
private sealed class StrChangeStyleMethod : FunctionMethod
{
StrFormType strType;
public StrChangeStyleMethod(StrFormType type)
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string) };
strType = type;
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string str = arguments[0].GetStrValue(exm, tryTranslate);
if (str == null || str == "")
return ("");
switch (strType)
{
case StrFormType.Upper:
return (str.ToUpper());
case StrFormType.Lower:
return (str.ToLower());
case StrFormType.Half:
return (Strings.StrConv(str, VbStrConv.Narrow, Config.Config.Language));
case StrFormType.Full:
return (Strings.StrConv(str, VbStrConv.Wide, Config.Config.Language));
}
return ("");
}
}
private sealed class LineIsEmptyMethod : FunctionMethod
{
public LineIsEmptyMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
return GlobalStatic.Console.EmptyLine ? 1L : 0L;
}
}
private sealed class ReplaceMethod : FunctionMethod
{
//Bartoum : Replace method
public ReplaceMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string), typeof(string), typeof(string) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string baseString = arguments[0].GetStrValue(exm, tryTranslate);
Regex reg;
try
{
reg = new Regex(arguments[1].GetStrValue(exm, tryTranslate));
}
catch (ArgumentException e)
{
throw new CodeEE("第2引数が正規表現として不正です:" + e.Message);
}
return (reg.Replace(baseString, arguments[2].GetStrValue(exm, tryTranslate)));
}
}
private sealed class UnicodeMethod : FunctionMethod
{
public UnicodeMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(Int64) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
Int64 i = arguments[0].GetIntValue(exm);
if ((i < 0) || (i > 0xFFFF))
throw new CodeEE("UNICODE関数に範囲外の値(" + i + ")が渡されました");
string s = new string(new[] { (char)i });// char.ConvertFromUtf32(i);
return (s);
}
}
private sealed class UnicodeByteMethod : FunctionMethod
{
public UnicodeByteMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string target = arguments[0].GetStrValue(exm);
int length = Encoding.UTF32.GetEncoder().GetByteCount(target.ToCharArray(), 0, target.Length, false);
byte[] bytes = new byte[length];
Encoding.UTF32.GetEncoder().GetBytes(target.ToCharArray(), 0, target.Length, bytes, 0, false);
Int64 i = BitConverter.ToInt32(bytes, 0);
return (i);
}
}
private sealed class ConvertIntMethod : FunctionMethod
{
public ConvertIntMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(Int64), typeof(Int64) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
Int64 toBase = arguments[1].GetIntValue(exm);
if ((toBase != 2) && (toBase != 8) && (toBase != 10) && (toBase != 16))
throw new CodeEE("CONVERT関数の第2引数は2, 8, 10, 16のいずれかでなければなりません");
return Convert.ToString(arguments[0].GetIntValue(exm), (int)toBase);
}
}
private sealed class IsNumericMethod : FunctionMethod
{
public IsNumericMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override long GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string baseStr = arguments[0].GetStrValue(exm);
//全角文字があるなら数値ではない
if (baseStr.Length < LangManager.GetStrlenLang(baseStr))
return (0);
StringStream st = new StringStream(baseStr);
if (!char.IsDigit(st.Current) && st.Current != '+' && st.Current != '-')
return (0);
if ((st.Current == '+' || st.Current == '-') && !char.IsDigit(st.Next))
return (0);
Int64 ret = LexicalAnalyzer.ReadInt64(st, true);
if (!st.EOS)
{
if (st.Current == '.')
{
st.ShiftNext();
while (!st.EOS)
{
if (!char.IsDigit(st.Current))
return (0);
st.ShiftNext();
}
}
else
return (0);
}
return 1;
}
}
private sealed class EscapeMethod : FunctionMethod
{
public EscapeMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
return Regex.Escape(arguments[0].GetStrValue(exm));
}
}
private sealed class EncodeToUniMethod : FunctionMethod
{
public EncodeToUniMethod()
{
ReturnType = typeof(Int64);
argumentTypeArray = new Type[] { null };
CanRestructure = true;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常2つ、1つ省略可能で1~2の引数が必要。
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 2)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (arguments[0].GetOperandType() != typeof(string))
return name + "関数の1番目の引数の型が正しくありません";
if ((arguments.Length >= 2) && (arguments[1] != null) && (arguments[1].GetOperandType() != typeof(Int64)))
return name + "関数の2番目の引数の型が正しくありません";
return null;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
string baseStr = arguments[0].GetStrValue(exm);
if (baseStr.Length == 0)
return -1;
Int64 position = (arguments.Length > 1 && arguments[1] != null) ? arguments[1].GetIntValue(exm) : 0;
if (position < 0)
throw new CodeEE("ENCOIDETOUNI関数の第2引数(" + position + ")が負の値です");
if (position >= baseStr.Length)
throw new CodeEE("ENCOIDETOUNI関数の第2引数(" + position + ")が第1引数の文字列(" + baseStr + ")の文字数を超えています");
return char.ConvertToUtf32(baseStr, (int)position);
}
}
public sealed class CharAtMethod : FunctionMethod
{
public CharAtMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string), typeof(Int64) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string str = arguments[0].GetStrValue(exm);
Int64 pos = arguments[1].GetIntValue(exm);
if (pos < 0 || pos >= str.Length)
return "";
return str[(int)pos].ToString();
}
}
public sealed class GetLineStrMethod : FunctionMethod
{
public GetLineStrMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string str = arguments[0].GetStrValue(exm);
if (string.IsNullOrEmpty(str))
throw new CodeEE("GETLINESTR関数の引数が空文字列です");
return exm.Console.getStBar(str);
}
}
public sealed class StrFormMethod : FunctionMethod
{
public StrFormMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string) };
HasUniqueRestructure = true;
CanRestructure = true;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
string str = arguments[0].GetStrValue(exm, tryTranslate);
string destStr = str;
try
{
StrFormWord wt = LexicalAnalyzer.AnalyseFormattedString(new StringStream(str), FormStrEndWith.EoL, false);
StrForm strForm = StrForm.FromWordToken(wt);
destStr = strForm.GetString(exm, tryTranslate);
}
catch(CodeEE e)
{
throw new CodeEE("STRFORM関数:文字列\"" + str + "\"の展開エラー:" + e.Message);
}
catch
{
throw new CodeEE("STRFORM関数:文字列\"" + str+ "\"の展開処理中にエラーが発生しました");
}
return destStr;
}
public override bool UniqueRestructure(ExpressionMediator exm, IOperandTerm[] arguments)
{
arguments[0].Restructure(exm);
//引数が文字列式等ならお手上げなので諦める
if (!(arguments[0] is SingleTerm) && !(arguments[0] is VariableTerm))
return false;
//引数が確定値でない文字列変数なら無条件で不可(結果が可変なため)
if ((arguments[0] is VariableTerm) && !(((VariableTerm)arguments[0]).Identifier.IsConst))
return false;
string str = arguments[0].GetStrValue(exm);
try
{
StrFormWord wt = LexicalAnalyzer.AnalyseFormattedString(new StringStream(str), FormStrEndWith.EoL, false);
StrForm strForm = StrForm.FromWordToken(wt);
if (!strForm.IsConst)
return false;
}
catch
{
//パースできないのはエラーがあるかここではわからないからとりあえず考えない
return false;
}
return true;
}
}
public sealed class JoinMethod : FunctionMethod
{
public JoinMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
HasUniqueRestructure = false;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
if (arguments.Length < 1)
return name + "関数には少なくとも1つの引数が必要です";
if (arguments.Length > 4)
return name + "関数の引数が多すぎます";
if (arguments[0] == null)
return name + "関数の1番目の引数は省略できません";
if (!(arguments[0] is VariableTerm))
return name + "関数の1番目の引数が変数ではありません";
VariableTerm varToken = (VariableTerm)arguments[0];
if (!varToken.Identifier.IsArray1D && !varToken.Identifier.IsArray2D && !varToken.Identifier.IsArray3D)
return name + "関数の1番目の引数が配列変数ではありません";
if (arguments.Length == 1)
return null;
if ((arguments[1] != null) && (arguments[1].GetOperandType() != typeof(string)))
return name + "関数の2番目の変数が文字列ではありません";
if (arguments.Length == 2)
return null;
if ((arguments[2] != null) && (arguments[2].GetOperandType() != typeof(Int64)))
return name + "関数の3番目の変数が数値ではありません";
if (arguments.Length == 3)
return null;
if ((arguments[3] != null) && (arguments[3].GetOperandType() != typeof(Int64)))
return name + "関数の4番目の変数が数値ではありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = true)
{
VariableTerm varTerm = (VariableTerm)arguments[0];
string delimiter = (arguments.Length >= 2 && arguments[1] != null) ? arguments[1].GetStrValue(exm) : ",";
Int64 index1 = (arguments.Length >= 3 && arguments[2] != null) ? arguments[2].GetIntValue(exm) : 0;
Int64 index2 = (arguments.Length == 4 && arguments[3] != null) ? arguments[3].GetIntValue(exm) : varTerm.GetLastLength();
FixedVariableTerm p = varTerm.GetFixedVariableTerm(exm);
p.IsArrayRangeValid(index1, index2, "STRJOIN", 2L, 3L);
return (exm.VEvaluator.GetJoinedStr(p, delimiter, index1, index2));
}
}
public sealed class GetConfigMethod : FunctionMethod
{
public GetConfigMethod(bool typeisInt)
{
if(typeisInt)
{
funcname = "GETCONFIG";
ReturnType = typeof(Int64);
}
else
{
funcname = "GETCONFIGS";
ReturnType = typeof(string);
}
argumentTypeArray = new[] { typeof(string) };
CanRestructure = true;
}
private readonly string funcname;
private SingleTerm getSingleTerm(ExpressionMediator exm, IOperandTerm[] arguments)
{
string str = arguments[0].GetStrValue(exm);
if(str == null || str.Length == 0)
throw new CodeEE(funcname + "関数に空文字列が渡されました");
string errMes = null;
SingleTerm term = ConfigData.Instance.GetConfigValueInERB(str, ref errMes);
if(errMes != null)
throw new CodeEE(funcname + "関数:" + errMes);
return term;
}
public override Int64 GetIntValue(ExpressionMediator exm, IOperandTerm[] arguments)
{
if(ReturnType != typeof(Int64))
throw new ExeEE(funcname + "関数:不正な呼び出し");
SingleTerm term = getSingleTerm(exm, arguments);
if(term.GetOperandType() != typeof(Int64))
throw new CodeEE(funcname + "関数:型が違います(GETCONFIGS関数を使用してください)");
return term.Int;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
if(ReturnType != typeof(string))
throw new ExeEE(funcname + "関数:不正な呼び出し");
SingleTerm term = getSingleTerm(exm, arguments);
if (term.GetOperandType() != typeof(string))
throw new CodeEE(funcname + "関数:型が違います(GETCONFIG関数を使用してください)");
return term.Str;
}
}
#endregion
#region html系
private sealed class HtmlGetPrintedStrMethod : FunctionMethod
{
public HtmlGetPrintedStrMethod()
{
ReturnType = typeof(string);
argumentTypeArray = null;
CanRestructure = false;
}
public override string CheckArgumentType(string name, IOperandTerm[] arguments)
{
//通常1つ。省略可能。
if (arguments.Length > 1)
return name + "関数の引数が多すぎます";
if (arguments.Length == 0|| arguments[0] == null)
return null;
if (arguments[0].GetOperandType() != typeof(Int64))
return name + "関数の1番目の引数の型が正しくありません";
return null;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
//Int64 lineNo = 0;
//if (arguments.Length > 0)
// lineNo = arguments[0].GetIntValue(exm);
//if (lineNo < 0)
// throw new CodeEE("引数を0未満にできません");
//ConsoleDisplayLine[] dispLines = exm.Console.GetDisplayLines(lineNo);
//if (dispLines == null)
// return "";
// return HtmlManager.DisplayLine2Html(dispLines, true);
return "";
}
}
private sealed class HtmlPopPrintingStrMethod : FunctionMethod
{
public HtmlPopPrintingStrMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new Type[] { };
CanRestructure = false;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
//ConsoleDisplayLine[] dispLines = exm.Console.PopDisplayingLines();
//if (dispLines == null)
// return "";
//return HtmlManager.DisplayLine2Html(dispLines, false);
return "";
}
}
private sealed class HtmlToPlainTextMethod : FunctionMethod
{
public HtmlToPlainTextMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = false;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
//return HtmlManager.Html2PlainText(arguments[0].GetStrValue(exm));
return "";
}
}
private sealed class HtmlEscapeMethod : FunctionMethod
{
public HtmlEscapeMethod()
{
ReturnType = typeof(string);
argumentTypeArray = new[] { typeof(string) };
CanRestructure = false;
}
public override string GetStrValue(ExpressionMediator exm, IOperandTerm[] arguments, bool tryTranslate = false)
{
//return HtmlManager.Escape(arguments[0].GetStrValue(exm));
return System.Security.SecurityElement.Escape(arguments[0].GetStrValue(exm));
}
}
#endregion
}
}