mirror of
https://github.com/chylex/Query.git
synced 2025-09-18 12:24:48 +02:00
Compare commits
11 Commits
71bf0a5c49
...
main
Author | SHA1 | Date | |
---|---|---|---|
9a280e0d58
|
|||
6caf8c7eb2
|
|||
1c92d67fa3
|
|||
963f8da60c
|
|||
b40fb751d0
|
|||
d52ec8a615
|
|||
5d640de7e5
|
|||
d69c4672d6
|
|||
f05d70ec14
|
|||
c138c2a3ea
|
|||
3debecb9a9
|
@@ -1,18 +1,19 @@
|
|||||||
using Calculator.Math;
|
using System.Collections.Immutable;
|
||||||
|
using Calculator.Math;
|
||||||
using Calculator.Parser;
|
using Calculator.Parser;
|
||||||
|
|
||||||
namespace Calculator;
|
namespace Calculator;
|
||||||
|
|
||||||
public sealed class CalculatorExpressionVisitor : ExpressionVisitor<NumberWithUnit> {
|
public sealed class CalculatorExpressionVisitor : ExpressionVisitor<NumberWithUnit> {
|
||||||
public NumberWithUnit VisitNumber(Expression.Number number) {
|
public NumberWithUnit VisitNumber(Expression.Number number) {
|
||||||
return new NumberWithUnit(number.NumberToken.Value, null);
|
return number.NumberToken.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public NumberWithUnit VisitNumbersWithUnits(Expression.NumbersWithUnits numbersWithUnits) {
|
public NumberWithUnit VisitNumbersWithUnits(Expression.NumbersWithUnits numbersWithUnits) {
|
||||||
NumberWithUnit result = new Number.Rational(0);
|
NumberWithUnit result = new Number.Rational(0);
|
||||||
|
|
||||||
foreach ((Token.Number number, Unit unit) in numbersWithUnits.NumberTokensWithUnits) {
|
foreach ((Token.Number number, Unit unit) in numbersWithUnits.NumberTokensWithUnits) {
|
||||||
result += new NumberWithUnit(number.Value, unit);
|
result += new NumberWithUnit(number.Value, [ unit ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
@@ -51,8 +52,8 @@ public sealed class CalculatorExpressionVisitor : ExpressionVisitor<NumberWithUn
|
|||||||
|
|
||||||
NumberWithUnit number = Evaluate(left);
|
NumberWithUnit number = Evaluate(left);
|
||||||
|
|
||||||
if (number.Unit is null) {
|
if (number.PrimaryUnit is null) {
|
||||||
return number with { Unit = right };
|
return new NumberWithUnit(number.Value, [ right ]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new CalculatorException("Expression already has a unit, cannot assign a new unit: " + right);
|
throw new CalculatorException("Expression already has a unit, cannot assign a new unit: " + right);
|
||||||
@@ -60,9 +61,9 @@ public sealed class CalculatorExpressionVisitor : ExpressionVisitor<NumberWithUn
|
|||||||
}
|
}
|
||||||
|
|
||||||
public NumberWithUnit VisitUnitConversion(Expression.UnitConversion unitConversion) {
|
public NumberWithUnit VisitUnitConversion(Expression.UnitConversion unitConversion) {
|
||||||
(Expression left, Unit unit) = unitConversion;
|
(Expression left, ImmutableArray<Unit> units) = unitConversion;
|
||||||
|
|
||||||
return Evaluate(left).ConvertTo(unit);
|
return Evaluate(left).ConvertTo(units);
|
||||||
}
|
}
|
||||||
|
|
||||||
private NumberWithUnit Evaluate(Expression expression) {
|
private NumberWithUnit Evaluate(Expression expression) {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
using ExtendedNumerics;
|
using ExtendedNumerics;
|
||||||
|
|
||||||
@@ -16,13 +17,21 @@ public abstract record Number : IAdditionOperators<Number, Number, Number>,
|
|||||||
IUnaryPlusOperators<Number, Number>,
|
IUnaryPlusOperators<Number, Number>,
|
||||||
IUnaryNegationOperators<Number, Number>,
|
IUnaryNegationOperators<Number, Number>,
|
||||||
IAdditiveIdentity<Number, Number.Rational>,
|
IAdditiveIdentity<Number, Number.Rational>,
|
||||||
IMultiplicativeIdentity<Number, Number.Rational> {
|
IMultiplicativeIdentity<Number, Number.Rational>,
|
||||||
|
IComparable<Number> {
|
||||||
protected abstract decimal AsDecimal { get; }
|
protected abstract decimal AsDecimal { get; }
|
||||||
|
|
||||||
|
public abstract Number WholePart { get; }
|
||||||
|
public abstract bool IsZero { get; }
|
||||||
|
|
||||||
public abstract Number Pow(Number exponent);
|
public abstract Number Pow(Number exponent);
|
||||||
|
|
||||||
public abstract string ToString(IFormatProvider? formatProvider);
|
public abstract string ToString(IFormatProvider? formatProvider);
|
||||||
|
|
||||||
|
public virtual int CompareTo(Number? other) {
|
||||||
|
return AsDecimal.CompareTo(other?.AsDecimal);
|
||||||
|
}
|
||||||
|
|
||||||
public sealed override string ToString() {
|
public sealed override string ToString() {
|
||||||
return ToString(CultureInfo.InvariantCulture);
|
return ToString(CultureInfo.InvariantCulture);
|
||||||
}
|
}
|
||||||
@@ -33,22 +42,63 @@ public abstract record Number : IAdditionOperators<Number, Number, Number>,
|
|||||||
public sealed record Rational(BigRational Value) : Number {
|
public sealed record Rational(BigRational Value) : Number {
|
||||||
protected override decimal AsDecimal => (decimal) Value;
|
protected override decimal AsDecimal => (decimal) Value;
|
||||||
|
|
||||||
|
public override Rational WholePart => new (Value.WholePart);
|
||||||
|
public override bool IsZero => Value.IsZero;
|
||||||
|
|
||||||
public override Number Pow(Number exponent) {
|
public override Number Pow(Number exponent) {
|
||||||
if (exponent is Rational { Value: {} rationalExponent }) {
|
if (exponent is Rational { Value: {} rationalExponent }) {
|
||||||
Fraction fractionExponent = rationalExponent.GetImproperFraction();
|
Fraction fractionExponent = Fraction.ReduceToProperFraction(rationalExponent.GetImproperFraction());
|
||||||
if (fractionExponent.Denominator == 1 && fractionExponent.Numerator >= 0) {
|
|
||||||
|
if (fractionExponent.Numerator >= 0 && fractionExponent.Denominator == 1) {
|
||||||
try {
|
try {
|
||||||
return new Rational(BigRational.Pow(Value, fractionExponent.Numerator));
|
return new Rational(BigRational.Pow(Value, fractionExponent.Numerator));
|
||||||
} catch (OverflowException) {}
|
} catch (OverflowException) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fractionExponent.Numerator == 1 && fractionExponent.Denominator > 1) {
|
||||||
|
Number result = PowAsDecimal(exponent);
|
||||||
|
|
||||||
|
BigRational assumedPerfectPowerRoot = new BigRational(decimal.Floor(result.AsDecimal));
|
||||||
|
BigRational assumedPerfectPower = BigRational.Pow(assumedPerfectPowerRoot, fractionExponent.Denominator);
|
||||||
|
|
||||||
|
return assumedPerfectPower == Value ? assumedPerfectPowerRoot : result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Decimal(AsDecimal).Pow(exponent);
|
return PowAsDecimal(exponent);
|
||||||
|
|
||||||
|
Number PowAsDecimal(Number number) {
|
||||||
|
return new Decimal(AsDecimal).Pow(number);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString(IFormatProvider? formatProvider) {
|
public override string ToString(IFormatProvider? formatProvider) {
|
||||||
Fraction fraction = Value.GetImproperFraction();
|
BigRational value = Fraction.ReduceToProperFraction(Value.GetImproperFraction());
|
||||||
return fraction.Denominator == 1 ? fraction.Numerator.ToString(formatProvider) : AsDecimal.ToString(formatProvider);
|
string wholePartStr = value.WholePart.ToString(formatProvider);
|
||||||
|
|
||||||
|
if (value.FractionalPart.IsZero) {
|
||||||
|
return wholePartStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
decimal fractionalPart = (decimal) value.FractionalPart;
|
||||||
|
|
||||||
|
if (fractionalPart == 0) {
|
||||||
|
return wholePartStr + ".0...";
|
||||||
|
}
|
||||||
|
|
||||||
|
string decimalPartStr = fractionalPart.ToString(formatProvider);
|
||||||
|
int decimalSeparatorIndex = decimalPartStr.TakeWhile(char.IsAsciiDigit).Count();
|
||||||
|
|
||||||
|
return wholePartStr + decimalPartStr[decimalSeparatorIndex..];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int CompareTo(Number? other) {
|
||||||
|
if (other is Rational rational) {
|
||||||
|
return Value.CompareTo(rational.Value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return base.CompareTo(other);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,6 +110,9 @@ public abstract record Number : IAdditionOperators<Number, Number, Number>,
|
|||||||
|
|
||||||
protected override decimal AsDecimal => Value;
|
protected override decimal AsDecimal => Value;
|
||||||
|
|
||||||
|
public override Decimal WholePart => new (decimal.Floor(Value));
|
||||||
|
public override bool IsZero => Value == 0;
|
||||||
|
|
||||||
public override Number Pow(Number exponent) {
|
public override Number Pow(Number exponent) {
|
||||||
double doubleValue = (double) Value;
|
double doubleValue = (double) Value;
|
||||||
double doubleExponent = (double) exponent.AsDecimal;
|
double doubleExponent = (double) exponent.AsDecimal;
|
||||||
|
@@ -1,33 +1,85 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using System.Numerics;
|
using System.Numerics;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Calculator.Math;
|
namespace Calculator.Math;
|
||||||
|
|
||||||
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
[SuppressMessage("ReSharper", "MemberCanBeInternal")]
|
||||||
public readonly record struct NumberWithUnit(Number Number, Unit? Unit) : IAdditionOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
public sealed class NumberWithUnit : IAdditionOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
||||||
ISubtractionOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
ISubtractionOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
||||||
IMultiplyOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
IMultiplyOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
||||||
IDivisionOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
IDivisionOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
||||||
IModulusOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
IModulusOperators<NumberWithUnit, NumberWithUnit, NumberWithUnit>,
|
||||||
IUnaryPlusOperators<NumberWithUnit, NumberWithUnit>,
|
IUnaryPlusOperators<NumberWithUnit, NumberWithUnit>,
|
||||||
IUnaryNegationOperators<NumberWithUnit, NumberWithUnit> {
|
IUnaryNegationOperators<NumberWithUnit, NumberWithUnit> {
|
||||||
public NumberWithUnit ConvertTo(Unit targetUnit) {
|
public Number Value { get; }
|
||||||
if (Unit == null) {
|
public Unit? PrimaryUnit => Unit?.Primary;
|
||||||
return this with { Unit = targetUnit };
|
|
||||||
|
private UnitDescription? Unit { get; }
|
||||||
|
|
||||||
|
private NumberWithUnit(Number value, UnitDescription? unit) {
|
||||||
|
this.Value = value;
|
||||||
|
this.Unit = unit;
|
||||||
}
|
}
|
||||||
else if (Units.All.TryGetUniverse(Unit, out var universe) && universe.TryConvert(Number, Unit, targetUnit, out var converted)) {
|
|
||||||
return new NumberWithUnit(converted, targetUnit);
|
public NumberWithUnit(Number value, ImmutableArray<Unit> units) : this(value, UnitDescription.From(units)) {}
|
||||||
|
|
||||||
|
private NumberWithUnit WithValue(Number value) {
|
||||||
|
return new NumberWithUnit(value, Unit);
|
||||||
|
}
|
||||||
|
|
||||||
|
public NumberWithUnit ConvertTo(ImmutableArray<Unit> targetUnits) {
|
||||||
|
if (targetUnits.IsEmpty || Unit == null) {
|
||||||
|
return new NumberWithUnit(Value, targetUnits);
|
||||||
|
}
|
||||||
|
else if (Unit.Universe.TryConvert(Value, Unit.Primary, targetUnits[0], out Number? converted)) {
|
||||||
|
return new NumberWithUnit(converted, targetUnits);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new ArithmeticException("Cannot convert '" + Unit + "' to '" + targetUnit + "'");
|
throw new ArithmeticException("Cannot convert '" + Unit.Primary + "' to '" + targetUnits[0] + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ToString(IFormatProvider? formatProvider) {
|
public string ToString(IFormatProvider? formatProvider) {
|
||||||
string number = Number.ToString(formatProvider);
|
if (Unit == null) {
|
||||||
return Unit == null ? number : number + " " + Unit;
|
return Value.ToString(formatProvider);
|
||||||
|
}
|
||||||
|
else if (Unit.Display.Length <= 1) {
|
||||||
|
return Value.ToString(formatProvider) + " " + Unit.Primary;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ImmutableArray<Unit> unitsFromLargest = [..Unit.Display.OrderByDescending(unit => Unit.Universe.Convert(value: 1, fromUnit: unit, toUnit: Unit.Primary))];
|
||||||
|
Unit smallestUnit = unitsFromLargest[^1];
|
||||||
|
Number remaining = Unit.Universe.Convert(Value, Unit.Primary, smallestUnit);
|
||||||
|
|
||||||
|
StringBuilder formatted = new StringBuilder();
|
||||||
|
|
||||||
|
void AppendNumberWithUnit(Number value, Unit unit) {
|
||||||
|
formatted.Append(value.ToString(formatProvider));
|
||||||
|
formatted.Append(' ');
|
||||||
|
formatted.Append(unit);
|
||||||
|
formatted.Append(' ');
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (Unit nextUnit in unitsFromLargest[..^1]) {
|
||||||
|
Number wholePart = Unit.Universe.Convert(remaining, smallestUnit, nextUnit).WholePart;
|
||||||
|
|
||||||
|
if (!wholePart.IsZero) {
|
||||||
|
AppendNumberWithUnit(wholePart, nextUnit);
|
||||||
|
remaining -= Unit.Universe.Convert(wholePart, nextUnit, smallestUnit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!remaining.IsZero || formatted.Length == 0) {
|
||||||
|
AppendNumberWithUnit(remaining, smallestUnit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatted.Remove(formatted.Length - 1, length: 1).ToString();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
@@ -35,23 +87,23 @@ public readonly record struct NumberWithUnit(Number Number, Unit? Unit) : IAddit
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static implicit operator NumberWithUnit(Number number) {
|
public static implicit operator NumberWithUnit(Number number) {
|
||||||
return new NumberWithUnit(number, null);
|
return new NumberWithUnit(number, unit: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NumberWithUnit operator +(NumberWithUnit value) {
|
public static NumberWithUnit operator +(NumberWithUnit value) {
|
||||||
return value with { Number = +value.Number };
|
return value.WithValue(+value.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NumberWithUnit operator -(NumberWithUnit value) {
|
public static NumberWithUnit operator -(NumberWithUnit value) {
|
||||||
return value with { Number = -value.Number };
|
return value.WithValue(-value.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static NumberWithUnit operator +(NumberWithUnit left, NumberWithUnit right) {
|
public static NumberWithUnit operator +(NumberWithUnit left, NumberWithUnit right) {
|
||||||
return Operate(left, right, Number.Add, static (leftNumber, leftUnit, rightNumber, rightUnit) => {
|
return Operate(left, right, Number.Add, static (leftNumber, leftUnit, rightNumber, rightUnit) => {
|
||||||
if (leftUnit == rightUnit) {
|
if (leftUnit.Primary == rightUnit.Primary) {
|
||||||
return new NumberWithUnit(leftNumber + rightNumber, leftUnit);
|
return new NumberWithUnit(leftNumber + rightNumber, leftUnit);
|
||||||
}
|
}
|
||||||
else if (Units.All.TryGetUniverse(leftUnit, out UnitUniverse? universe) && universe.TryConvert(rightNumber, rightUnit, leftUnit, out Number? rightConverted)) {
|
else if (rightUnit.Universe.TryConvert(rightNumber, fromUnit: rightUnit.Primary, toUnit: leftUnit.Primary, out Number? rightConverted)) {
|
||||||
return new NumberWithUnit(leftNumber + rightConverted, leftUnit);
|
return new NumberWithUnit(leftNumber + rightConverted, leftUnit);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -62,10 +114,10 @@ public readonly record struct NumberWithUnit(Number Number, Unit? Unit) : IAddit
|
|||||||
|
|
||||||
public static NumberWithUnit operator -(NumberWithUnit left, NumberWithUnit right) {
|
public static NumberWithUnit operator -(NumberWithUnit left, NumberWithUnit right) {
|
||||||
return Operate(left, right, Number.Subtract, static (leftNumber, leftUnit, rightNumber, rightUnit) => {
|
return Operate(left, right, Number.Subtract, static (leftNumber, leftUnit, rightNumber, rightUnit) => {
|
||||||
if (leftUnit == rightUnit) {
|
if (leftUnit.Primary == rightUnit.Primary) {
|
||||||
return new NumberWithUnit(leftNumber - rightNumber, leftUnit);
|
return new NumberWithUnit(leftNumber - rightNumber, leftUnit);
|
||||||
}
|
}
|
||||||
else if (Units.All.TryGetUniverse(leftUnit, out UnitUniverse? universe) && universe.TryConvert(rightNumber, rightUnit, leftUnit, out Number? rightConverted)) {
|
else if (rightUnit.Universe.TryConvert(rightNumber, fromUnit: rightUnit.Primary, toUnit: leftUnit.Primary, out Number? rightConverted)) {
|
||||||
return new NumberWithUnit(leftNumber - rightConverted, leftUnit);
|
return new NumberWithUnit(leftNumber - rightConverted, leftUnit);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -90,19 +142,44 @@ public readonly record struct NumberWithUnit(Number Number, Unit? Unit) : IAddit
|
|||||||
return OperateWithoutUnits(this, exponent, Number.Pow, "Cannot exponentiate");
|
return OperateWithoutUnits(this, exponent, Number.Pow, "Cannot exponentiate");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NumberWithUnit Operate(NumberWithUnit left, NumberWithUnit right, Func<Number, Number, Number> withoutUnitsOperation, Func<Number, Unit, Number, Unit, NumberWithUnit> withUnitsOperation) {
|
private static NumberWithUnit Operate(NumberWithUnit left, NumberWithUnit right, Func<Number, Number, Number> withoutUnitsOperation, Func<Number, UnitDescription, Number, UnitDescription, NumberWithUnit> withUnitsOperation) {
|
||||||
if (right.Unit is null) {
|
if (right.Unit is null) {
|
||||||
return left with { Number = withoutUnitsOperation(left.Number, right.Number) };
|
return left.WithValue(withoutUnitsOperation(left.Value, right.Value));
|
||||||
}
|
}
|
||||||
else if (left.Unit is null) {
|
else if (left.Unit is null) {
|
||||||
return right with { Number = withoutUnitsOperation(left.Number, right.Number) };
|
return right.WithValue(withoutUnitsOperation(left.Value, right.Value));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return withUnitsOperation(left.Number, left.Unit, right.Number, right.Unit);
|
return withUnitsOperation(left.Value, left.Unit, right.Value, right.Unit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static NumberWithUnit OperateWithoutUnits(NumberWithUnit left, NumberWithUnit right, Func<Number, Number, Number> withoutUnitsOperation, string messagePrefix) {
|
private static NumberWithUnit OperateWithoutUnits(NumberWithUnit left, NumberWithUnit right, Func<Number, Number, Number> withoutUnitsOperation, string messagePrefix) {
|
||||||
return Operate(left, right, withoutUnitsOperation, (_, leftUnit, _, rightUnit) => throw new ArithmeticException(messagePrefix + " '" + leftUnit + "' and '" + rightUnit + "'"));
|
return Operate(left, right, withoutUnitsOperation, (_, leftUnit, _, rightUnit) => throw new ArithmeticException(messagePrefix + " '" + leftUnit + "' and '" + rightUnit + "'"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed record UnitDescription(Unit Primary, ImmutableArray<Unit> Display, UnitUniverse Universe) {
|
||||||
|
public static UnitDescription? From(ImmutableArray<Unit> units) {
|
||||||
|
if (units.IsEmpty) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Units.All.TryGetUniverse(units[0], out UnitUniverse? primaryUnitUniverse)) {
|
||||||
|
throw new ArgumentException("Unknown unit universe: " + units[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int index = 1; index < units.Length; index++) {
|
||||||
|
Unit secondaryUnit = units[index];
|
||||||
|
|
||||||
|
if (!Units.All.TryGetUniverse(secondaryUnit, out UnitUniverse? secondaryUnitUniverse)) {
|
||||||
|
throw new ArgumentException("Unknown unit universe: " + secondaryUnit);
|
||||||
|
}
|
||||||
|
else if (primaryUnitUniverse != secondaryUnitUniverse) {
|
||||||
|
throw new ArgumentException("All units must be from the same universe: " + secondaryUnitUniverse + " != " + primaryUnitUniverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new UnitDescription(units[0], units, primaryUnitUniverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -10,11 +10,16 @@ using ExtendedNumerics;
|
|||||||
namespace Calculator.Math;
|
namespace Calculator.Math;
|
||||||
|
|
||||||
sealed class UnitUniverse(
|
sealed class UnitUniverse(
|
||||||
|
string name,
|
||||||
FrozenDictionary<Unit, Func<Number, Number>> unitToConversionToPrimaryUnit,
|
FrozenDictionary<Unit, Func<Number, Number>> unitToConversionToPrimaryUnit,
|
||||||
FrozenDictionary<Unit, Func<Number, Number>> unitToConversionFromPrimaryUnit
|
FrozenDictionary<Unit, Func<Number, Number>> unitToConversionFromPrimaryUnit
|
||||||
) {
|
) {
|
||||||
public ImmutableArray<Unit> AllUnits => unitToConversionToPrimaryUnit.Keys;
|
public ImmutableArray<Unit> AllUnits => unitToConversionToPrimaryUnit.Keys;
|
||||||
|
|
||||||
|
internal Number Convert(Number value, Unit fromUnit, Unit toUnit) {
|
||||||
|
return TryConvert(value, fromUnit, toUnit, out var converted) ? converted : throw new ArgumentException("Cannot convert from " + fromUnit + " to " + toUnit);
|
||||||
|
}
|
||||||
|
|
||||||
internal bool TryConvert(Number value, Unit fromUnit, Unit toUnit, [NotNullWhen(true)] out Number? converted) {
|
internal bool TryConvert(Number value, Unit fromUnit, Unit toUnit, [NotNullWhen(true)] out Number? converted) {
|
||||||
if (fromUnit == toUnit) {
|
if (fromUnit == toUnit) {
|
||||||
converted = value;
|
converted = value;
|
||||||
@@ -30,43 +35,49 @@ sealed class UnitUniverse(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override string ToString() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
internal sealed record SI(string ShortPrefix, string LongPrefix, int Factor) {
|
internal sealed record SI(string ShortPrefix, string LongPrefix, int Factor) {
|
||||||
internal static readonly List<SI> All = [
|
internal static readonly List<SI> All = [
|
||||||
new SI("Q", "quetta", 30),
|
new ("Q", "quetta", Factor: 30),
|
||||||
new SI("R", "ronna", 27),
|
new ("R", "ronna", Factor: 27),
|
||||||
new SI("Y", "yotta", 24),
|
new ("Y", "yotta", Factor: 24),
|
||||||
new SI("Z", "zetta", 21),
|
new ("Z", "zetta", Factor: 21),
|
||||||
new SI("E", "exa", 18),
|
new ("E", "exa", Factor: 18),
|
||||||
new SI("P", "peta", 15),
|
new ("P", "peta", Factor: 15),
|
||||||
new SI("T", "tera", 12),
|
new ("T", "tera", Factor: 12),
|
||||||
new SI("G", "giga", 9),
|
new ("G", "giga", Factor: 9),
|
||||||
new SI("M", "mega", 6),
|
new ("M", "mega", Factor: 6),
|
||||||
new SI("k", "kilo", 3),
|
new ("k", "kilo", Factor: 3),
|
||||||
new SI("h", "hecto", 2),
|
new ("h", "hecto", Factor: 2),
|
||||||
new SI("da", "deca", 1),
|
new ("da", "deca", Factor: 1),
|
||||||
new SI("d", "deci", -1),
|
new ("d", "deci", Factor: -1),
|
||||||
new SI("c", "centi", -2),
|
new ("c", "centi", Factor: -2),
|
||||||
new SI("m", "milli", -3),
|
new ("m", "milli", Factor: -3),
|
||||||
new SI("μ", "micro", -6),
|
new ("μ", "micro", Factor: -6),
|
||||||
new SI("n", "nano", -9),
|
new ("n", "nano", Factor: -9),
|
||||||
new SI("p", "pico", -12),
|
new ("p", "pico", Factor: -12),
|
||||||
new SI("f", "femto", -15),
|
new ("f", "femto", Factor: -15),
|
||||||
new SI("a", "atto", -18),
|
new ("a", "atto", Factor: -18),
|
||||||
new SI("z", "zepto", -21),
|
new ("z", "zepto", Factor: -21),
|
||||||
new SI("y", "yocto", -24),
|
new ("y", "yocto", Factor: -24),
|
||||||
new SI("r", "ronto", -27),
|
new ("r", "ronto", Factor: -27),
|
||||||
new SI("q", "quecto", -30)
|
new ("q", "quecto", Factor: -30),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
internal sealed class Builder {
|
internal sealed class Builder {
|
||||||
|
private readonly string name;
|
||||||
private readonly Unit primaryUnit;
|
private readonly Unit primaryUnit;
|
||||||
private readonly Dictionary<Unit, Func<Number, Number>> unitToConversionToPrimaryUnit = new (ReferenceEqualityComparer.Instance);
|
private readonly Dictionary<Unit, Func<Number, Number>> unitToConversionToPrimaryUnit = new (ReferenceEqualityComparer.Instance);
|
||||||
private readonly Dictionary<Unit, Func<Number, Number>> unitToConversionFromPrimaryUnit = new (ReferenceEqualityComparer.Instance);
|
private readonly Dictionary<Unit, Func<Number, Number>> unitToConversionFromPrimaryUnit = new (ReferenceEqualityComparer.Instance);
|
||||||
|
|
||||||
public Builder(Unit primaryUnit) {
|
public Builder(string name, Unit primaryUnit) {
|
||||||
|
this.name = name;
|
||||||
this.primaryUnit = primaryUnit;
|
this.primaryUnit = primaryUnit;
|
||||||
AddUnit(primaryUnit, 1);
|
AddUnit(primaryUnit, amountInPrimaryUnit: 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder AddUnit(Unit unit, Func<Number, Number> convertToPrimaryUnit, Func<Number, Number> convertFromPrimaryUnit) {
|
public Builder AddUnit(Unit unit, Func<Number, Number> convertToPrimaryUnit, Func<Number, Number> convertFromPrimaryUnit) {
|
||||||
@@ -81,8 +92,8 @@ sealed class UnitUniverse(
|
|||||||
|
|
||||||
private void AddUnitSI(SI si, Func<SI, Unit> unitFactory, Func<int, int> factorModifier) {
|
private void AddUnitSI(SI si, Func<SI, Unit> unitFactory, Func<int, int> factorModifier) {
|
||||||
int factor = factorModifier(si.Factor);
|
int factor = factorModifier(si.Factor);
|
||||||
BigInteger powerOfTen = BigInteger.Pow(10, System.Math.Abs(factor));
|
BigInteger powerOfTen = BigInteger.Pow(value: 10, System.Math.Abs(factor));
|
||||||
BigRational amountInPrimaryUnit = factor > 0 ? new BigRational(powerOfTen) : new BigRational(1, powerOfTen);
|
BigRational amountInPrimaryUnit = factor > 0 ? new BigRational(powerOfTen) : new BigRational(numerator: 1, powerOfTen);
|
||||||
AddUnit(unitFactory(si), amountInPrimaryUnit);
|
AddUnit(unitFactory(si), amountInPrimaryUnit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +123,7 @@ sealed class UnitUniverse(
|
|||||||
|
|
||||||
public UnitUniverse Build() {
|
public UnitUniverse Build() {
|
||||||
return new UnitUniverse(
|
return new UnitUniverse(
|
||||||
|
name,
|
||||||
unitToConversionToPrimaryUnit.ToFrozenDictionary(ReferenceEqualityComparer.Instance),
|
unitToConversionToPrimaryUnit.ToFrozenDictionary(ReferenceEqualityComparer.Instance),
|
||||||
unitToConversionFromPrimaryUnit.ToFrozenDictionary(ReferenceEqualityComparer.Instance)
|
unitToConversionFromPrimaryUnit.ToFrozenDictionary(ReferenceEqualityComparer.Instance)
|
||||||
);
|
);
|
||||||
|
@@ -26,7 +26,7 @@ static class Units {
|
|||||||
var day = hour * 24;
|
var day = hour * 24;
|
||||||
var week = day * 7;
|
var week = day * 7;
|
||||||
|
|
||||||
return new UnitUniverse.Builder(new Unit("s", Pluralize("second")))
|
return new UnitUniverse.Builder("Time", new Unit("s", Pluralize("second")))
|
||||||
.AddUnit(new Unit("min", Pluralize("minute")), minute)
|
.AddUnit(new Unit("min", Pluralize("minute")), minute)
|
||||||
.AddUnit(new Unit("h", Pluralize("hour")), hour)
|
.AddUnit(new Unit("h", Pluralize("hour")), hour)
|
||||||
.AddUnit(new Unit("d", Pluralize("day")), day)
|
.AddUnit(new Unit("d", Pluralize("day")), day)
|
||||||
@@ -42,7 +42,7 @@ static class Units {
|
|||||||
var nauticalMile = 1_852;
|
var nauticalMile = 1_852;
|
||||||
var lightYear = 9_460_730_472_580_800;
|
var lightYear = 9_460_730_472_580_800;
|
||||||
|
|
||||||
return new UnitUniverse.Builder(new Unit("m", Pluralize("meter", "metre")))
|
return new UnitUniverse.Builder("Length", new Unit("m", Pluralize("meter", "metre")))
|
||||||
.AddSI()
|
.AddSI()
|
||||||
.AddUnit(new Unit("in", [ "inch", "inches", "\"" ]), inch)
|
.AddUnit(new Unit("in", [ "inch", "inches", "\"" ]), inch)
|
||||||
.AddUnit(new Unit("ft", [ "foot", "feet", "'" ]), foot)
|
.AddUnit(new Unit("ft", [ "foot", "feet", "'" ]), foot)
|
||||||
@@ -59,7 +59,7 @@ static class Units {
|
|||||||
var ounce = pound / 16;
|
var ounce = pound / 16;
|
||||||
var dram = ounce / 16;
|
var dram = ounce / 16;
|
||||||
|
|
||||||
return new UnitUniverse.Builder(new Unit("g", Pluralize("gram")))
|
return new UnitUniverse.Builder("Mass", new Unit("g", Pluralize("gram")))
|
||||||
.AddSI()
|
.AddSI()
|
||||||
.AddUnit(new Unit("lb", [ "lbs", "pound", "pounds" ]), pound)
|
.AddUnit(new Unit("lb", [ "lbs", "pound", "pounds" ]), pound)
|
||||||
.AddUnit(new Unit("st", Pluralize("stone")), stone)
|
.AddUnit(new Unit("st", Pluralize("stone")), stone)
|
||||||
@@ -81,10 +81,10 @@ static class Units {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UnitUniverse.Builder(SquareMeter(string.Empty, string.Empty))
|
return new UnitUniverse.Builder("Area", SquareMeter(string.Empty, string.Empty))
|
||||||
.AddSI(static si => SquareMeter(si.ShortPrefix, si.LongPrefix), static factor => factor * 2)
|
.AddSI(static si => SquareMeter(si.ShortPrefix, si.LongPrefix), static factor => factor * 2)
|
||||||
.AddUnit(new Unit("a", Pluralize("are")), 100)
|
.AddUnit(new Unit("a", Pluralize("are")), amountInPrimaryUnit: 100)
|
||||||
.AddUnit(new Unit("ha", Pluralize("hectare")), 10_000);
|
.AddUnit(new Unit("ha", Pluralize("hectare")), amountInPrimaryUnit: 10_000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UnitUniverse.Builder VolumeUniverse() {
|
private static UnitUniverse.Builder VolumeUniverse() {
|
||||||
@@ -100,42 +100,42 @@ static class Units {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new UnitUniverse.Builder(new Unit("l", Pluralize("litre", "liter")))
|
return new UnitUniverse.Builder("Volume", new Unit("l", Pluralize("litre", "liter")))
|
||||||
.AddSI()
|
.AddSI()
|
||||||
.AddUnit(CubicMeter(string.Empty, string.Empty), 1000)
|
.AddUnit(CubicMeter(string.Empty, string.Empty), amountInPrimaryUnit: 1000)
|
||||||
.AddSI(static si => CubicMeter(si.ShortPrefix, si.LongPrefix), static factor => (factor * 3) + 3);
|
.AddSI(static si => CubicMeter(si.ShortPrefix, si.LongPrefix), static factor => (factor * 3) + 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UnitUniverse.Builder AngleUniverse() {
|
private static UnitUniverse.Builder AngleUniverse() {
|
||||||
return new UnitUniverse.Builder(new Unit("deg", [ "°", "degree", "degrees" ]))
|
return new UnitUniverse.Builder("Angle", new Unit("deg", [ "°", "degree", "degrees" ]))
|
||||||
.AddUnit(new Unit("rad", Pluralize("radian")), new Number.Decimal((decimal) System.Math.PI / 180M))
|
.AddUnit(new Unit("rad", Pluralize("radian")), new Number.Decimal((decimal) System.Math.PI / 180M))
|
||||||
.AddUnit(new Unit("grad", Pluralize("gradian", "grade", "gon")), Ratio(9, 10));
|
.AddUnit(new Unit("grad", Pluralize("gradian", "grade", "gon")), Ratio(numerator: 9, denominator: 10));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BigRational KelvinOffset { get; } = Parse("273", "15");
|
private static BigRational KelvinOffset { get; } = Parse("273", "15");
|
||||||
|
|
||||||
private static UnitUniverse.Builder TemperatureUniverse() {
|
private static UnitUniverse.Builder TemperatureUniverse() {
|
||||||
return new UnitUniverse.Builder(new Unit("°C", [ "C", "Celsius", "celsius" ]))
|
return new UnitUniverse.Builder("Temperature", new Unit("°C", [ "C", "Celsius", "celsius" ]))
|
||||||
.AddUnit(new Unit("°F", [ "F", "Fahrenheit", "fahrenheit" ]), static f => (f - 32) * Ratio(5, 9), static c => c * Ratio(9, 5) + 32)
|
.AddUnit(new Unit("°F", [ "F", "Fahrenheit", "fahrenheit" ]), static f => (f - 32) * Ratio(numerator: 5, denominator: 9), static c => c * Ratio(numerator: 9, denominator: 5) + 32)
|
||||||
.AddUnit(new Unit("K", [ "Kelvin", "kelvin" ]), static k => k - KelvinOffset, static c => c + KelvinOffset);
|
.AddUnit(new Unit("K", [ "Kelvin", "kelvin" ]), static k => k - KelvinOffset, static c => c + KelvinOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static UnitUniverse.Builder InformationEntropyUniverse() {
|
private static UnitUniverse.Builder InformationEntropyUniverse() {
|
||||||
var bit = Ratio(1, 8);
|
var bit = Ratio(numerator: 1, denominator: 8);
|
||||||
var nibble = bit * 4;
|
var nibble = bit * 4;
|
||||||
|
|
||||||
return new UnitUniverse.Builder(new Unit("B", Pluralize("byte")))
|
return new UnitUniverse.Builder("Information Entropy", new Unit("B", Pluralize("byte")))
|
||||||
.AddSI()
|
.AddSI()
|
||||||
.AddUnit(new Unit("b", Pluralize("bit")), bit)
|
.AddUnit(new Unit("b", Pluralize("bit")), bit)
|
||||||
.AddUnit(new Unit("nibbles", [ "nibble" ]), nibble)
|
.AddUnit(new Unit("nibbles", [ "nibble" ]), nibble)
|
||||||
.AddUnit(new Unit("KiB", Pluralize("kibibyte")), Pow(1024, 1))
|
.AddUnit(new Unit("KiB", Pluralize("kibibyte")), Pow(value: 1024, exponent: 1))
|
||||||
.AddUnit(new Unit("MiB", Pluralize("mebibyte")), Pow(1024, 2))
|
.AddUnit(new Unit("MiB", Pluralize("mebibyte")), Pow(value: 1024, exponent: 2))
|
||||||
.AddUnit(new Unit("GiB", Pluralize("gibibyte")), Pow(1024, 3))
|
.AddUnit(new Unit("GiB", Pluralize("gibibyte")), Pow(value: 1024, exponent: 3))
|
||||||
.AddUnit(new Unit("TiB", Pluralize("tebibyte")), Pow(1024, 4))
|
.AddUnit(new Unit("TiB", Pluralize("tebibyte")), Pow(value: 1024, exponent: 4))
|
||||||
.AddUnit(new Unit("PiB", Pluralize("pebibyte")), Pow(1024, 5))
|
.AddUnit(new Unit("PiB", Pluralize("pebibyte")), Pow(value: 1024, exponent: 5))
|
||||||
.AddUnit(new Unit("EiB", Pluralize("exbibyte")), Pow(1024, 6))
|
.AddUnit(new Unit("EiB", Pluralize("exbibyte")), Pow(value: 1024, exponent: 6))
|
||||||
.AddUnit(new Unit("ZiB", Pluralize("zebibyte")), Pow(1024, 7))
|
.AddUnit(new Unit("ZiB", Pluralize("zebibyte")), Pow(value: 1024, exponent: 7))
|
||||||
.AddUnit(new Unit("YiB", Pluralize("yobibyte")), Pow(1024, 8));
|
.AddUnit(new Unit("YiB", Pluralize("yobibyte")), Pow(value: 1024, exponent: 8));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BigRational Parse(string integerPart, string fractionalPart) {
|
private static BigRational Parse(string integerPart, string fractionalPart) {
|
||||||
|
@@ -49,7 +49,7 @@ public abstract record Expression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed record UnitConversion(Expression Left, Unit Unit) : Expression {
|
public sealed record UnitConversion(Expression Left, ImmutableArray<Unit> Units) : Expression {
|
||||||
public override T Accept<T>(ExpressionVisitor<T> visitor) {
|
public override T Accept<T>(ExpressionVisitor<T> visitor) {
|
||||||
return visitor.VisitUnitConversion(this);
|
return visitor.VisitUnitConversion(this);
|
||||||
}
|
}
|
||||||
|
@@ -12,17 +12,17 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
|
|
||||||
private static readonly ImmutableArray<SimpleTokenType> PLUS_MINUS = [
|
private static readonly ImmutableArray<SimpleTokenType> PLUS_MINUS = [
|
||||||
SimpleTokenType.PLUS,
|
SimpleTokenType.PLUS,
|
||||||
SimpleTokenType.MINUS
|
SimpleTokenType.MINUS,
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly ImmutableArray<SimpleTokenType> STAR_SLASH_PERCENT = [
|
private static readonly ImmutableArray<SimpleTokenType> STAR_SLASH_PERCENT = [
|
||||||
SimpleTokenType.STAR,
|
SimpleTokenType.STAR,
|
||||||
SimpleTokenType.SLASH,
|
SimpleTokenType.SLASH,
|
||||||
SimpleTokenType.PERCENT
|
SimpleTokenType.PERCENT,
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly ImmutableArray<SimpleTokenType> CARET = [
|
private static readonly ImmutableArray<SimpleTokenType> CARET = [
|
||||||
SimpleTokenType.CARET
|
SimpleTokenType.CARET,
|
||||||
];
|
];
|
||||||
|
|
||||||
private bool Match(SimpleTokenType expectedTokenType, [NotNullWhen(true)] out Token.Simple? token) {
|
private bool Match(SimpleTokenType expectedTokenType, [NotNullWhen(true)] out Token.Simple? token) {
|
||||||
@@ -51,6 +51,15 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
public Expression Parse() {
|
public Expression Parse() {
|
||||||
Expression term = Term();
|
Expression term = Term();
|
||||||
|
|
||||||
|
if (Match<Token.Text>(static text => text.Value is "to" or "in", out _)) {
|
||||||
|
if (MatchOneOrMoreUnits(out ImmutableArray<Unit> units)) {
|
||||||
|
term = new Expression.UnitConversion(term, units);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new ParseException("Expected one or more unit literals");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!IsEOF) {
|
if (!IsEOF) {
|
||||||
throw new ParseException("Incomplete expression");
|
throw new ParseException("Incomplete expression");
|
||||||
}
|
}
|
||||||
@@ -67,7 +76,7 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private Expression Exponentiation() {
|
private Expression Exponentiation() {
|
||||||
return Binary(Conversion, CARET);
|
return Binary(Unary, CARET);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression Binary(Func<Expression> term, ImmutableArray<SimpleTokenType> expectedTokenTypes) {
|
private Expression Binary(Func<Expression> term, ImmutableArray<SimpleTokenType> expectedTokenTypes) {
|
||||||
@@ -81,20 +90,6 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expression Conversion() {
|
|
||||||
Expression left = Unary();
|
|
||||||
|
|
||||||
while (MatchUnitConversionOperator()) {
|
|
||||||
if (!MatchUnit(out Unit? unit)) {
|
|
||||||
throw new ParseException("Expected a unit literal");
|
|
||||||
}
|
|
||||||
|
|
||||||
left = new Expression.UnitConversion(left, unit);
|
|
||||||
}
|
|
||||||
|
|
||||||
return left;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Expression Unary() {
|
private Expression Unary() {
|
||||||
if (Match(PLUS_MINUS, out Token.Simple? op)) {
|
if (Match(PLUS_MINUS, out Token.Simple? op)) {
|
||||||
Expression right = Unary();
|
Expression right = Unary();
|
||||||
@@ -152,17 +147,6 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
throw new ParseException("Expected ')' after expression.");
|
throw new ParseException("Expected ')' after expression.");
|
||||||
}
|
}
|
||||||
|
|
||||||
int position = current;
|
|
||||||
|
|
||||||
if (MatchUnitConversionOperator()) {
|
|
||||||
if (MatchUnit(out Unit? toUnit)) {
|
|
||||||
return new Expression.UnitConversion(term, toUnit);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
current = position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (MatchUnit(out Unit? unit)) {
|
if (MatchUnit(out Unit? unit)) {
|
||||||
return new Expression.UnitAssignment(term, unit);
|
return new Expression.UnitAssignment(term, unit);
|
||||||
}
|
}
|
||||||
@@ -185,6 +169,23 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool MatchOneOrMoreUnits(out ImmutableArray<Unit> units) {
|
||||||
|
if (!MatchUnit(out Unit? nextUnit)) {
|
||||||
|
units = ImmutableArray<Unit>.Empty;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = ImmutableArray.CreateBuilder<Unit>();
|
||||||
|
|
||||||
|
do {
|
||||||
|
result.Add(nextUnit);
|
||||||
|
Match<Token.Text>(static text => text.Value is "and", out _);
|
||||||
|
} while (MatchUnit(out nextUnit));
|
||||||
|
|
||||||
|
units = result.ToImmutable();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool MatchUnit([NotNullWhen(true)] out Unit? unit) {
|
private bool MatchUnit([NotNullWhen(true)] out Unit? unit) {
|
||||||
int position = current;
|
int position = current;
|
||||||
|
|
||||||
@@ -205,8 +206,4 @@ public sealed class Parser(ImmutableArray<Token> tokens) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool MatchUnitConversionOperator() {
|
|
||||||
return Match<Token.Text>(static text => text.Value is "to" or "in", out _);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>chylex</Authors>
|
<Authors>chylex</Authors>
|
||||||
<Version>2.0.0.0</Version>
|
<Version>2.3.0.0</Version>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
|
146
Query/Form/MainForm.Designer.cs
generated
146
Query/Form/MainForm.Designer.cs
generated
@@ -23,109 +23,107 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.components = new System.ComponentModel.Container();
|
components = new System.ComponentModel.Container();
|
||||||
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
|
||||||
this.queryLog = new QueryHistoryLog();
|
queryLog = new Query.Form.QueryHistoryLog();
|
||||||
this.queryBox = new QueryTextBox();
|
queryBox = new Query.Form.QueryTextBox();
|
||||||
this.trayIcon = new System.Windows.Forms.NotifyIcon(this.components);
|
trayIcon = new System.Windows.Forms.NotifyIcon(components);
|
||||||
this.contextMenuTray = new System.Windows.Forms.ContextMenuStrip(this.components);
|
contextMenuTray = new System.Windows.Forms.ContextMenuStrip(components);
|
||||||
this.showToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
showToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.hookToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
hookToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
|
||||||
this.contextMenuTray.SuspendLayout();
|
contextMenuTray.SuspendLayout();
|
||||||
this.SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// queryLog
|
// queryLog
|
||||||
//
|
//
|
||||||
this.queryLog.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
queryLog.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right));
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
queryLog.BackColor = System.Drawing.Color.Transparent;
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
queryLog.Font = new System.Drawing.Font("Consolas", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) 238));
|
||||||
this.queryLog.BackColor = System.Drawing.Color.Transparent;
|
queryLog.Location = new System.Drawing.Point(7, 8);
|
||||||
this.queryLog.Font = new System.Drawing.Font("Consolas", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
queryLog.Margin = new System.Windows.Forms.Padding(7, 8, 7, 8);
|
||||||
this.queryLog.Location = new System.Drawing.Point(5, 5);
|
queryLog.Name = "queryLog";
|
||||||
this.queryLog.Margin = new System.Windows.Forms.Padding(5);
|
queryLog.Size = new System.Drawing.Size(696, 296);
|
||||||
this.queryLog.Name = "queryLog";
|
queryLog.TabIndex = 1;
|
||||||
this.queryLog.Size = new System.Drawing.Size(522, 192);
|
|
||||||
this.queryLog.TabIndex = 1;
|
|
||||||
//
|
//
|
||||||
// queryBox
|
// queryBox
|
||||||
//
|
//
|
||||||
this.queryBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
|
queryBox.BackColor = System.Drawing.Color.FromArgb(((int) ((byte) 36)), ((int) ((byte) 36)), ((int) ((byte) 36)));
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
queryBox.Dock = System.Windows.Forms.DockStyle.Bottom;
|
||||||
this.queryBox.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(36)))), ((int)(((byte)(36)))), ((int)(((byte)(36)))));
|
queryBox.Location = new System.Drawing.Point(0, 312);
|
||||||
this.queryBox.Location = new System.Drawing.Point(0, 202);
|
queryBox.Margin = new System.Windows.Forms.Padding(0);
|
||||||
this.queryBox.Margin = new System.Windows.Forms.Padding(0);
|
queryBox.Name = "queryBox";
|
||||||
this.queryBox.Name = "queryBox";
|
queryBox.Size = new System.Drawing.Size(709, 50);
|
||||||
this.queryBox.Size = new System.Drawing.Size(532, 33);
|
queryBox.TabIndex = 0;
|
||||||
this.queryBox.TabIndex = 0;
|
|
||||||
//
|
//
|
||||||
// trayIcon
|
// trayIcon
|
||||||
//
|
//
|
||||||
this.trayIcon.ContextMenuStrip = this.contextMenuTray;
|
trayIcon.ContextMenuStrip = contextMenuTray;
|
||||||
this.trayIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("trayIcon.Icon")));
|
trayIcon.Icon = ((System.Drawing.Icon) resources.GetObject("trayIcon.Icon"));
|
||||||
this.trayIcon.Text = "Query";
|
trayIcon.Text = "Query";
|
||||||
this.trayIcon.Visible = true;
|
trayIcon.Visible = true;
|
||||||
this.trayIcon.Click += new System.EventHandler(this.trayIcon_Click);
|
trayIcon.Click += trayIcon_Click;
|
||||||
//
|
//
|
||||||
// contextMenuTray
|
// contextMenuTray
|
||||||
//
|
//
|
||||||
this.contextMenuTray.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
contextMenuTray.ImageScalingSize = new System.Drawing.Size(20, 20);
|
||||||
this.showToolStripMenuItem,
|
contextMenuTray.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
|
||||||
this.hookToolStripMenuItem,
|
showToolStripMenuItem, hookToolStripMenuItem, exitToolStripMenuItem
|
||||||
this.exitToolStripMenuItem});
|
});
|
||||||
this.contextMenuTray.Name = "contextMenuTray";
|
contextMenuTray.Name = "contextMenuTray";
|
||||||
this.contextMenuTray.ShowImageMargin = false;
|
contextMenuTray.ShowImageMargin = false;
|
||||||
this.contextMenuTray.ShowItemToolTips = false;
|
contextMenuTray.ShowItemToolTips = false;
|
||||||
this.contextMenuTray.Size = new System.Drawing.Size(128, 92);
|
contextMenuTray.Size = new System.Drawing.Size(90, 76);
|
||||||
//
|
//
|
||||||
// showToolStripMenuItem
|
// showToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.showToolStripMenuItem.Name = "showToolStripMenuItem";
|
showToolStripMenuItem.Name = "showToolStripMenuItem";
|
||||||
this.showToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
|
showToolStripMenuItem.Size = new System.Drawing.Size(89, 24);
|
||||||
this.showToolStripMenuItem.Text = "Show";
|
showToolStripMenuItem.Text = "Show";
|
||||||
this.showToolStripMenuItem.Click += new System.EventHandler(this.showToolStripMenuItem_Click);
|
showToolStripMenuItem.Click += showToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// hookToolStripMenuItem
|
// hookToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.hookToolStripMenuItem.Name = "hookToolStripMenuItem";
|
hookToolStripMenuItem.Name = "hookToolStripMenuItem";
|
||||||
this.hookToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
|
hookToolStripMenuItem.Size = new System.Drawing.Size(89, 24);
|
||||||
this.hookToolStripMenuItem.Text = "Hook";
|
hookToolStripMenuItem.Text = "Hook";
|
||||||
this.hookToolStripMenuItem.Click += new System.EventHandler(this.hookToolStripMenuItem_Click);
|
hookToolStripMenuItem.Click += hookToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// exitToolStripMenuItem
|
// exitToolStripMenuItem
|
||||||
//
|
//
|
||||||
this.exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
exitToolStripMenuItem.Name = "exitToolStripMenuItem";
|
||||||
this.exitToolStripMenuItem.Size = new System.Drawing.Size(127, 22);
|
exitToolStripMenuItem.Size = new System.Drawing.Size(89, 24);
|
||||||
this.exitToolStripMenuItem.Text = "Exit";
|
exitToolStripMenuItem.Text = "Exit";
|
||||||
this.exitToolStripMenuItem.Click += new System.EventHandler(this.exitToolStripMenuItem_Click);
|
exitToolStripMenuItem.Click += exitToolStripMenuItem_Click;
|
||||||
//
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(64)))), ((int)(((byte)(64)))));
|
BackColor = System.Drawing.Color.FromArgb(((int) ((byte) 64)), ((int) ((byte) 64)), ((int) ((byte) 64)));
|
||||||
this.ClientSize = new System.Drawing.Size(532, 235);
|
ClientSize = new System.Drawing.Size(709, 362);
|
||||||
this.ControlBox = false;
|
ControlBox = false;
|
||||||
this.Controls.Add(this.queryLog);
|
Controls.Add(queryLog);
|
||||||
this.Controls.Add(this.queryBox);
|
Controls.Add(queryBox);
|
||||||
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
|
||||||
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
|
Icon = ((System.Drawing.Icon) resources.GetObject("$this.Icon"));
|
||||||
this.MaximizeBox = false;
|
Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||||
this.MinimizeBox = false;
|
MaximizeBox = false;
|
||||||
this.Name = "MainForm";
|
MinimizeBox = false;
|
||||||
this.ShowInTaskbar = false;
|
ShowInTaskbar = false;
|
||||||
this.Text = "Query";
|
Text = "Query";
|
||||||
this.Deactivate += new System.EventHandler(this.MainForm_Deactivate);
|
Deactivate += MainForm_Deactivate;
|
||||||
this.Shown += new System.EventHandler(this.MainForm_Shown);
|
Shown += MainForm_Shown;
|
||||||
this.contextMenuTray.ResumeLayout(false);
|
LocationChanged += MainForm_LocationChanged;
|
||||||
this.ResumeLayout(false);
|
SizeChanged += MainForm_SizeChanged;
|
||||||
|
contextMenuTray.ResumeLayout(false);
|
||||||
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private QueryTextBox queryBox;
|
private Query.Form.QueryTextBox queryBox;
|
||||||
private QueryHistoryLog queryLog;
|
private Query.Form.QueryHistoryLog queryLog;
|
||||||
private System.Windows.Forms.NotifyIcon trayIcon;
|
private System.Windows.Forms.NotifyIcon trayIcon;
|
||||||
private System.Windows.Forms.ContextMenuStrip contextMenuTray;
|
private System.Windows.Forms.ContextMenuStrip contextMenuTray;
|
||||||
private System.Windows.Forms.ToolStripMenuItem showToolStripMenuItem;
|
private System.Windows.Forms.ToolStripMenuItem showToolStripMenuItem;
|
||||||
|
@@ -45,10 +45,7 @@ sealed partial class MainForm : System.Windows.Forms.Form {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void MainForm_Shown(object? sender, EventArgs e) {
|
private void MainForm_Shown(object? sender, EventArgs e) {
|
||||||
if (Screen.PrimaryScreen is {} primaryScreen) {
|
FixLocation();
|
||||||
Rectangle screenRect = primaryScreen.WorkingArea;
|
|
||||||
Location = new Point(screenRect.X + screenRect.Width - Width, screenRect.Y + screenRect.Height - Height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isLoaded) {
|
if (!isLoaded) {
|
||||||
isLoaded = true;
|
isLoaded = true;
|
||||||
@@ -56,6 +53,25 @@ sealed partial class MainForm : System.Windows.Forms.Form {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MainForm_LocationChanged(object sender, EventArgs e) {
|
||||||
|
FixLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void MainForm_SizeChanged(object sender, EventArgs e) {
|
||||||
|
FixLocation();
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool isMoving = false;
|
||||||
|
|
||||||
|
private void FixLocation() {
|
||||||
|
if (!isMoving && WindowState != FormWindowState.Minimized && Screen.FromControl(this) is {} screen) {
|
||||||
|
Rectangle screenRect = screen.WorkingArea;
|
||||||
|
isMoving = true;
|
||||||
|
Location = new Point(screenRect.X + screenRect.Width - Width, screenRect.Y + screenRect.Height - Height);
|
||||||
|
isMoving = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void MainForm_Deactivate(object? sender, EventArgs e) {
|
private void MainForm_Deactivate(object? sender, EventArgs e) {
|
||||||
SetShown(false);
|
SetShown(false);
|
||||||
}
|
}
|
||||||
|
@@ -1,64 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<root>
|
<root>
|
||||||
<!--
|
|
||||||
Microsoft ResX Schema
|
|
||||||
|
|
||||||
Version 2.0
|
|
||||||
|
|
||||||
The primary goals of this format is to allow a simple XML format
|
|
||||||
that is mostly human readable. The generation and parsing of the
|
|
||||||
various data types are done through the TypeConverter classes
|
|
||||||
associated with the data types.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
... ado.net/XML headers & schema ...
|
|
||||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
|
||||||
<resheader name="version">2.0</resheader>
|
|
||||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
|
||||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
|
||||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
|
||||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
|
||||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
|
||||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
|
||||||
</data>
|
|
||||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
|
||||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
|
||||||
<comment>This is a comment</comment>
|
|
||||||
</data>
|
|
||||||
|
|
||||||
There are any number of "resheader" rows that contain simple
|
|
||||||
name/value pairs.
|
|
||||||
|
|
||||||
Each data row contains a name, and value. The row also contains a
|
|
||||||
type or mimetype. Type corresponds to a .NET class that support
|
|
||||||
text/value conversion through the TypeConverter architecture.
|
|
||||||
Classes that don't support this are serialized and stored with the
|
|
||||||
mimetype set.
|
|
||||||
|
|
||||||
The mimetype is used for serialized objects, and tells the
|
|
||||||
ResXResourceReader how to depersist the object. This is currently not
|
|
||||||
extensible. For a given mimetype the value must be set accordingly:
|
|
||||||
|
|
||||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
|
||||||
that the ResXResourceWriter will generate, however the reader can
|
|
||||||
read any of the formats listed below.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.binary.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.soap.base64
|
|
||||||
value : The object must be serialized with
|
|
||||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
|
|
||||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
|
||||||
value : The object must be serialized into a byte array
|
|
||||||
: using a System.ComponentModel.TypeConverter
|
|
||||||
: and then encoded with base64 encoding.
|
|
||||||
-->
|
|
||||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||||
<xsd:element name="root" msdata:IsDataSet="true">
|
<xsd:element name="root" msdata:IsDataSet="true">
|
||||||
@@ -112,19 +53,19 @@
|
|||||||
<value>2.0</value>
|
<value>2.0</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="reader">
|
<resheader name="reader">
|
||||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<resheader name="writer">
|
<resheader name="writer">
|
||||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
</resheader>
|
</resheader>
|
||||||
<metadata name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="trayIcon.TrayLocation" type="System.Drawing.Point, System.Drawing.Primitives, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>17, 17</value>
|
<value>17, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
<metadata name="contextMenuTray.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
<metadata name="contextMenuTray.TrayLocation" type="System.Drawing.Point, System.Drawing.Primitives, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
|
||||||
<value>112, 17</value>
|
<value>112, 17</value>
|
||||||
</metadata>
|
</metadata>
|
||||||
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
|
<assembly alias="System.Drawing.Common" name="System.Drawing.Common, Version=8.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
|
||||||
<data name="trayIcon.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="trayIcon.Icon" type="System.Drawing.Icon, System.Drawing.Common" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
AAABAAEAGBgAAAEAIACICQAAFgAAACgAAAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAABAAEAGBgAAAEAIACICQAAFgAAACgAAAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAkJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQk
|
AAAkJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQk
|
||||||
@@ -170,7 +111,7 @@
|
|||||||
AEE=
|
AEE=
|
||||||
</value>
|
</value>
|
||||||
</data>
|
</data>
|
||||||
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing.Common" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||||
<value>
|
<value>
|
||||||
AAABAAEAGBgAAAEAIACICQAAFgAAACgAAAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
AAABAAEAGBgAAAEAIACICQAAFgAAACgAAAAYAAAAMAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
||||||
AAAkJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQk
|
AAAkJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQkJP8kJCT/JCQk/yQk
|
||||||
|
39
Query/Form/QueryHistoryLog.Designer.cs
generated
39
Query/Form/QueryHistoryLog.Designer.cs
generated
@@ -23,31 +23,32 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.container = new System.Windows.Forms.FlowLayoutPanel();
|
container = new System.Windows.Forms.FlowLayoutPanel();
|
||||||
this.SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// container
|
// container
|
||||||
//
|
//
|
||||||
this.container.AutoScroll = true;
|
container.AutoScroll = true;
|
||||||
this.container.Dock = System.Windows.Forms.DockStyle.Fill;
|
container.Dock = System.Windows.Forms.DockStyle.Fill;
|
||||||
this.container.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
|
container.FlowDirection = System.Windows.Forms.FlowDirection.TopDown;
|
||||||
this.container.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
|
container.ForeColor = System.Drawing.Color.FromArgb(((int) ((byte) 240)), ((int) ((byte) 240)), ((int) ((byte) 240)));
|
||||||
this.container.Location = new System.Drawing.Point(0, 0);
|
container.Location = new System.Drawing.Point(0, 0);
|
||||||
this.container.Name = "container";
|
container.Margin = new System.Windows.Forms.Padding(4);
|
||||||
this.container.Size = new System.Drawing.Size(150, 150);
|
container.Name = "container";
|
||||||
this.container.TabIndex = 0;
|
container.Size = new System.Drawing.Size(195, 191);
|
||||||
this.container.WrapContents = false;
|
container.TabIndex = 0;
|
||||||
|
container.WrapContents = false;
|
||||||
//
|
//
|
||||||
// QueryHistoryLog
|
// QueryHistoryLog
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 22F);
|
AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.BackColor = System.Drawing.Color.Transparent;
|
BackColor = System.Drawing.Color.Transparent;
|
||||||
this.Controls.Add(this.container);
|
Controls.Add(container);
|
||||||
this.Font = new System.Drawing.Font("Consolas", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
Font = new System.Drawing.Font("Consolas", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) 238));
|
||||||
this.Name = "QueryHistoryLog";
|
Margin = new System.Windows.Forms.Padding(4);
|
||||||
this.ResumeLayout(false);
|
Size = new System.Drawing.Size(195, 191);
|
||||||
|
ResumeLayout(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
45
Query/Form/QueryTextBox.Designer.cs
generated
45
Query/Form/QueryTextBox.Designer.cs
generated
@@ -23,39 +23,36 @@
|
|||||||
/// the contents of this method with the code editor.
|
/// the contents of this method with the code editor.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void InitializeComponent() {
|
private void InitializeComponent() {
|
||||||
this.tb = new CustomTextBox();
|
tb = new Query.Form.QueryTextBox.CustomTextBox();
|
||||||
this.SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// tb
|
// tb
|
||||||
//
|
//
|
||||||
this.tb.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
|
tb.Anchor = ((System.Windows.Forms.AnchorStyles) (((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right));
|
||||||
| System.Windows.Forms.AnchorStyles.Left)
|
tb.BackColor = System.Drawing.Color.FromArgb(((int) ((byte) 36)), ((int) ((byte) 36)), ((int) ((byte) 36)));
|
||||||
| System.Windows.Forms.AnchorStyles.Right)));
|
tb.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
||||||
this.tb.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(36)))), ((int)(((byte)(36)))), ((int)(((byte)(36)))));
|
tb.Font = new System.Drawing.Font("Consolas", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte) 238));
|
||||||
this.tb.BorderStyle = System.Windows.Forms.BorderStyle.None;
|
tb.ForeColor = System.Drawing.Color.FromArgb(((int) ((byte) 240)), ((int) ((byte) 240)), ((int) ((byte) 240)));
|
||||||
this.tb.Font = new System.Drawing.Font("Consolas", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
|
tb.Location = new System.Drawing.Point(11, 11);
|
||||||
this.tb.ForeColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
|
tb.Margin = new System.Windows.Forms.Padding(11);
|
||||||
this.tb.Location = new System.Drawing.Point(5, 6);
|
tb.Name = "tb";
|
||||||
this.tb.Margin = new System.Windows.Forms.Padding(5);
|
tb.Size = new System.Drawing.Size(670, 28);
|
||||||
this.tb.Name = "tb";
|
tb.TabIndex = 0;
|
||||||
this.tb.Size = new System.Drawing.Size(509, 23);
|
|
||||||
this.tb.TabIndex = 0;
|
|
||||||
//
|
//
|
||||||
// QueryTextBox
|
// QueryTextBox
|
||||||
//
|
//
|
||||||
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
|
AutoScaleDimensions = new System.Drawing.SizeF(8F, 20F);
|
||||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||||
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(36)))), ((int)(((byte)(36)))), ((int)(((byte)(36)))));
|
BackColor = System.Drawing.Color.FromArgb(((int) ((byte) 36)), ((int) ((byte) 36)), ((int) ((byte) 36)));
|
||||||
this.Controls.Add(this.tb);
|
Controls.Add(tb);
|
||||||
this.Name = "QueryTextBox";
|
Margin = new System.Windows.Forms.Padding(4, 5, 4, 5);
|
||||||
this.Size = new System.Drawing.Size(519, 33);
|
Size = new System.Drawing.Size(692, 50);
|
||||||
this.ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
this.PerformLayout();
|
PerformLayout();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
private CustomTextBox tb;
|
private Query.Form.QueryTextBox.CustomTextBox tb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,6 +8,7 @@ static class Program {
|
|||||||
[STAThread]
|
[STAThread]
|
||||||
private static void Main() {
|
private static void Main() {
|
||||||
Application.EnableVisualStyles();
|
Application.EnableVisualStyles();
|
||||||
|
Application.SetHighDpiMode(HighDpiMode.PerMonitorV2);
|
||||||
Application.SetCompatibleTextRenderingDefault(false);
|
Application.SetCompatibleTextRenderingDefault(false);
|
||||||
Application.Run(new MainForm());
|
Application.Run(new MainForm());
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user