Example #1
0
        public (object, KalkExpression) Canonical(KalkExpression value)
        {
            Collect(value);
            SquashPowers();

            // Compute the final canonical value
            KalkExpression leftValue = null;

            if (_powers != null)
            {
                for (var i = 0; i < _powers.Count; i++)
                {
                    var power      = _powers[i];
                    var powerValue = _context.ToObject <double>(_context.CurrentSpan, power.Unit);
                    if (powerValue < 0)
                    {
                        powerValue = -powerValue;
                        power.Unit = powerValue;
                        object left = leftValue ?? (object)1.0;
                        leftValue = new KalkBinaryExpression(left, ScriptBinaryOperator.Divide, KalkValue.AlmostEqual(powerValue, 1.0) ? power.Value : power);
                    }
                    else
                    {
                        var nextMul = KalkValue.AlmostEqual(powerValue, 1.0) ? (KalkUnit)power.Value : (KalkExpression)power;
                        leftValue = leftValue == null ? nextMul : new KalkBinaryExpression(leftValue, ScriptBinaryOperator.Multiply, nextMul);
                    }
                }
            }


            return(_value, leftValue);
        }
Example #2
0
 public static bool Equals(TemplateContext context, KalkExpression left, KalkExpression right)
 {
     if (ReferenceEquals(null, right))
     {
         return(false);
     }
     if (ReferenceEquals(left, right))
     {
         return(true);
     }
     return(right.GetType() == left.GetType() && left.EqualsImpl(context, right));
 }
Example #3
0
        public KalkExpression ConvertTo(TemplateContext context, KalkExpression dst)
        {
            var src = this;

            var destExpr = dst.OriginalExpression ?? dst;

            var span = context.CurrentSpan;

            if (!this.TryEvaluate(context, span, ScriptBinaryOperator.Divide, span, this, span, dst, out var result) || result is KalkExpression)
            {
                throw new ScriptRuntimeException(context.CurrentSpan, $"Cannot convert the expression {src} to the unit `{destExpr}`. Units are not matching.");
            }

            var value = context.ToObject <double>(span, result);

            return(new KalkBinaryExpression(value, ScriptBinaryOperator.Multiply, dst.OriginalExpression));
        }
Example #4
0
 protected abstract bool EqualsImpl(TemplateContext context, KalkExpression right);
Example #5
0
 private static ScriptRuntimeException NotMatching(SourceSpan leftSpan, KalkExpression leftExpr, SourceSpan rightSpan, KalkExpression rightExpr)
 {
     return(new ScriptRuntimeException(leftExpr == null ? leftSpan : rightSpan, $"Missing unit for the {(leftExpr == null ? "left" : "right")} expression. It must match the unit of the other expression `{leftExpr ?? rightExpr}`."));
 }
Example #6
0
 public KalkExpression ConvertTo(KalkExpression src, KalkExpression dst)
 {
     return(src.ConvertTo(this, dst));
 }
Example #7
0
        public KalkExpression RegisterUnit(KalkUnit unit, string description = null, string symbol = null, KalkExpression value = null, string plural = null, string prefix = null, bool isUser = false)
        {
            if (unit == null)
            {
                throw new ArgumentNullException(nameof(unit));
            }
            var name = unit.Name;

            symbol ??= name;

            // Override isUser
            if (_registerAsSystem)
            {
                isUser = false;
            }

            CheckVariableAvailable(name, nameof(name), false);

            var prefixList = new List <KalkUnitPrefix>();

            if (prefix != null)
            {
                var prefixes = prefix.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
                foreach (var prefixItem in prefixes)
                {
                    if (prefixItem == "decimal")
                    {
                        prefixList.AddRange(KalkUnitPrefix.GetDecimals());
                    }
                    else if (prefixItem == "binary")
                    {
                        prefixList.AddRange(KalkUnitPrefix.GetBinaries());
                    }
                    else if (KalkUnitPrefix.TryGet(prefixItem, out var descriptor))
                    {
                        prefixList.Add(descriptor);
                    }
                    else
                    {
                        throw new ArgumentException($"The prefix `{prefixItem}` does not exist.", nameof(prefix));
                    }
                }
                prefixList = prefixList.Distinct().ToList();
            }

            // Pre-check all prefix with name/symbol
            foreach (var prefixDesc in prefixList)
            {
                var prefixWithName = $"{prefixDesc.Name}{name}";
                CheckVariableAvailable(prefixWithName, nameof(name), false);

                var prefixWithSymbol = $"{prefixDesc.Prefix}{symbol}";
                CheckVariableAvailable(prefixWithSymbol, nameof(name), false);
            }

            unit.Description = description;
            unit.Symbol      = symbol;
            unit.Value       = value;
            unit.IsUser      = isUser;
            unit.Prefix      = prefix;
            if (plural != null)
            {
                unit.Plural = plural;
            }

            if (unit.Symbol != unit.Name)
            {
                CheckVariableAvailable(unit.Symbol, nameof(symbol), false);
            }

            if (unit.Plural != unit.Name)
            {
                CheckVariableAvailable(unit.Plural, nameof(plural), false);
            }

            // Here we are all done after checking everything

            Units.Add(name, unit);


            if (unit.Symbol != unit.Name)
            {
                Units.Add(unit.Symbol, unit);
            }

            if (unit.Plural != unit.Name)
            {
                Units.Add(unit.Plural, unit);
            }

            // Register prefixes
            foreach (var prefixDesc in prefixList)
            {
                var prefixWithName   = $"{prefixDesc.Name}{unit.Name}";
                var prefixWithSymbol = $"{prefixDesc.Prefix}{unit.Symbol}";

                var unitPrefix = new KalkUnit(prefixWithName)
                {
                    Description = description,
                    Symbol      = prefixWithSymbol,
                    Value       = new KalkBinaryExpression(Math.Pow(prefixDesc.Base, prefixDesc.Exponent), ScriptBinaryOperator.Multiply, unit),
                    IsUser      = isUser,
                    Parent      = unit,
                };
                unit.Derived.Add(unitPrefix);

                Units.Add(prefixWithName, unitPrefix);
                Units.Add(prefixWithSymbol, unitPrefix);
            }

            return(unit);
        }
Example #8
0
 public KalkExpression DefineUserUnit(ScriptVariable name, string description = null, ScriptVariable symbol = null, KalkExpression value = null, string plural = null, string prefix = null)
 {
     if (name == null || string.IsNullOrEmpty(name.Name))
     {
         throw new ArgumentNullException(nameof(name));
     }
     return(RegisterUnit(new KalkUnit(name.Name), description, symbol?.Name, value, plural, prefix, isUser: true));
 }