Exemplo n.º 1
0
        public override SucoType GetBinaryOperatorType(BinaryOperator op, SucoType rightType, SucoContext context) => (op, rightType) switch
        {
            // Decimal op Decimal
            (BinaryOperator.Equal, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.NotEqual, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.LessThan, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.LessThanOrEqual, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.GreaterThan, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.GreaterThanOrEqual, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.Plus, SucoDecimalType) => SucoType.Decimal,
            (BinaryOperator.Minus, SucoDecimalType) => SucoType.Decimal,
            (BinaryOperator.Times, SucoDecimalType) => SucoType.Decimal,
            (BinaryOperator.Modulo, SucoDecimalType) => SucoType.Decimal,
            (BinaryOperator.Divide, SucoDecimalType) => SucoType.Decimal,
            (BinaryOperator.Power, SucoDecimalType) => SucoType.Decimal,

            // Decimal op Int
            (BinaryOperator.Equal, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.NotEqual, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.LessThan, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.LessThanOrEqual, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.GreaterThan, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.GreaterThanOrEqual, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.Plus, SucoIntegerType) => SucoType.Decimal,
            (BinaryOperator.Minus, SucoIntegerType) => SucoType.Decimal,
            (BinaryOperator.Times, SucoIntegerType) => SucoType.Decimal,
            (BinaryOperator.Modulo, SucoIntegerType) => SucoType.Decimal,
            (BinaryOperator.Divide, SucoIntegerType) => SucoType.Decimal,
            (BinaryOperator.Power, SucoIntegerType) => SucoType.Decimal,
            _ => base.GetBinaryOperatorType(op, rightType, context),
        };
Exemplo n.º 2
0
        public override SucoType GetBinaryOperatorType(BinaryOperator op, SucoType rightType, SucoContext context) => (op, rightType) switch
        {
            // Comparison with Int
            (BinaryOperator.Equal, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.NotEqual, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.LessThan, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.LessThanOrEqual, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.GreaterThan, SucoIntegerType) => SucoType.Boolean,
            (BinaryOperator.GreaterThanOrEqual, SucoIntegerType) => SucoType.Boolean,

            // Comparison with Decimal
            (BinaryOperator.Equal, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.NotEqual, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.LessThan, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.LessThanOrEqual, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.GreaterThan, SucoDecimalType) => SucoType.Boolean,
            (BinaryOperator.GreaterThanOrEqual, SucoDecimalType) => SucoType.Boolean,

            // Arithmetic with Int
            (BinaryOperator.Plus, SucoIntegerType) => SucoType.Integer,
            (BinaryOperator.Minus, SucoIntegerType) => SucoType.Integer,
            (BinaryOperator.Times, SucoIntegerType) => SucoType.Integer,
            (BinaryOperator.Modulo, SucoIntegerType) => SucoType.Integer,
            (BinaryOperator.Divide, SucoIntegerType) => context != SucoContext.Constraint ? SucoType.Decimal : throw new SucoTempCompileException("Suco does not allow the use of division in puzzle constraints. Rewrite the equation to use multiplication instead (for example: instead of a.value/b.value = 2, write a.value = 2*b.value)."),
                  (BinaryOperator.Power, SucoIntegerType) => SucoType.Integer,

                  // Arithmetic with Decimal
                  (BinaryOperator.Plus, SucoDecimalType) => SucoType.Decimal,
                  (BinaryOperator.Minus, SucoDecimalType) => SucoType.Decimal,
                  (BinaryOperator.Times, SucoDecimalType) => SucoType.Decimal,
                  (BinaryOperator.Modulo, SucoDecimalType) => SucoType.Decimal,
                  (BinaryOperator.Power, SucoDecimalType) => SucoType.Decimal,
                  _ => base.GetBinaryOperatorType(op, rightType, context),
        };
Exemplo n.º 3
0
 public override SucoType GetBinaryOperatorType(BinaryOperator op, SucoType rightType, SucoContext context) => (op, rightType) switch
 {
     (BinaryOperator.Equal, SucoBooleanType) => SucoType.Boolean,
     (BinaryOperator.NotEqual, SucoBooleanType) => SucoType.Boolean,
     (BinaryOperator.And, SucoBooleanType) => SucoType.Boolean,
     (BinaryOperator.Or, SucoBooleanType) => SucoType.Boolean,
     _ => base.GetBinaryOperatorType(op, rightType, context)
 };
Exemplo n.º 4
0
 public SucoListClause(int startIndex, int endIndex, string variableName, bool hasDollar, bool hasPlus, bool hasSingleton, SucoExpression fromExpression, List <SucoListCondition> conditions, SucoType varType = null)
     : base(startIndex, endIndex)
 {
     VariableName   = variableName;
     HasDollar      = hasDollar;
     HasPlus        = hasPlus;
     HasSingleton   = hasSingleton;
     FromExpression = fromExpression;
     Conditions     = conditions;
     VariableType   = varType;
 }
Exemplo n.º 5
0
        public override SucoListCondition DeduceTypes(SucoTypeEnvironment env, SucoContext context, SucoType elementType)
        {
            switch (Name)
            {
            case "first":
            case "last":
            case "before":
            case "after":
            case "~":
                break;

            case "^":
            case ">":
            case "v":
            case "<":
            case "↑":
            case "→":
            case "↓":
            case "←":
            case "diagonal":
            case "adjacent":
            case "orthogonal":
            case "above":
            case "right":
            case "below":
            case "left":
            case "samerow":
            case "samecol":
            case "samebox":
            case "topleft":
            case "topright":
            case "bottomleft":
            case "bottomright":
            case "lefttop":
            case "righttop":
            case "leftbottom":
            case "rightbottom":
                if (!elementType.Equals(SucoType.Cell))
                {
                    throw new SucoCompileException($"“{Name}” can only be used on lists of cells.", StartIndex, EndIndex);
                }
                break;

            default:
                throw new SucoCompileException($"Unknown shortcut condition: “{Name}”.", StartIndex, EndIndex);
            }
            return(this);
        }
Exemplo n.º 6
0
 public override bool Equals(SucoType other) => other is SucoListType list && list.ElementType.Equals(ElementType);
Exemplo n.º 7
0
 public SucoCallExpression(int startIndex, int endIndex, SucoExpression operand, SucoExpression[] arguments, SucoType type = null)
     : base(startIndex, endIndex, type)
 {
     Operand   = operand;
     Arguments = arguments;
 }
Exemplo n.º 8
0
        public override object InterpretBinaryOperator(object left, BinaryOperator @operator, SucoType rightType, object right) => (@operator, rightType) switch
        {
            // Comparison with Int
            (BinaryOperator.Equal, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a == b),
            (BinaryOperator.NotEqual, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a != b),
            (BinaryOperator.LessThan, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a < b),
            (BinaryOperator.LessThanOrEqual, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a <= b),
            (BinaryOperator.GreaterThan, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a > b),
            (BinaryOperator.GreaterThanOrEqual, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a >= b),

            // Comparison with Decimal
            (BinaryOperator.Equal, SucoDecimalType) => (int)left == (double)right,
            (BinaryOperator.NotEqual, SucoDecimalType) => (int)left != (double)right,
            (BinaryOperator.LessThan, SucoDecimalType) => (int)left <(double)right,
                                                                     (BinaryOperator.LessThanOrEqual, SucoDecimalType) => (int)left <= (double)right,
                                                                     (BinaryOperator.GreaterThan, SucoDecimalType) => (int)left> (double) right,
            (BinaryOperator.GreaterThanOrEqual, SucoDecimalType) => (int)left >= (double)right,

            // Integer arithmetic
            (BinaryOperator.Plus, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a + b),
            (BinaryOperator.Minus, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a - b),
            (BinaryOperator.Times, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => a * b),
            (BinaryOperator.Modulo, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => (a % b + b) % b),
            (BinaryOperator.Divide, SucoIntegerType) => (double)(int)left / (int)right,
            (BinaryOperator.Power, SucoIntegerType) => op((int?)left, (int?)right, (a, b) => (int)BigInteger.Pow(a, b)),

            // Decimal arithmetic
            (BinaryOperator.Plus, SucoDecimalType) => (int)left + (double)right,
            (BinaryOperator.Minus, SucoDecimalType) => (int)left - (double)right,
            (BinaryOperator.Times, SucoDecimalType) => (int)left * (double)right,
            (BinaryOperator.Modulo, SucoDecimalType) => ((int)left % (double)right + (double)right) % (double)right,
            (BinaryOperator.Power, SucoDecimalType) => Math.Pow((int)left, (double)right),

            _ => base.InterpretBinaryOperator(left, @operator, rightType, right),
        };
Exemplo n.º 9
0
 public SucoListComprehensionExpression(int startIndex, int endIndex, List <SucoListClause> clauses, SucoExpression selector, SucoType type = null)
     : base(startIndex, endIndex, type)
 {
     Clauses  = clauses ?? throw new ArgumentNullException(nameof(clauses));
     Selector = selector ?? throw new ArgumentNullException(nameof(selector));
 }
Exemplo n.º 10
0
 public static bool IsValidCode(string source, SucoTypeEnvironment env, SucoContext context, SucoType expectedResultType, out string error)
 {
     try
     {
         ParseCode(source, env, context, expectedResultType);
         error = null;
         return(true);
     }
     catch (SucoCompileException sce)
     {
         error = sce.Message;
         return(false);
     }
     catch (SucoParseException spe)
     {
         error = spe.Message;
         return(false);
     }
 }
Exemplo n.º 11
0
 public SucoVariable(string name, SucoType type)
 {
     Name = name;
     Type = type;
 }
Exemplo n.º 12
0
        public override object InterpretBinaryOperator(object left, BinaryOperator op, SucoType rightType, object right) => (op, rightType) switch
        {
            // Decimal op Decimal
            (BinaryOperator.Equal, SucoDecimalType) => (double)left == (double)right,
            (BinaryOperator.NotEqual, SucoDecimalType) => (double)left != (double)right,
            (BinaryOperator.LessThan, SucoDecimalType) => (double)left <(double)right,
                                                                        (BinaryOperator.LessThanOrEqual, SucoDecimalType) => (double)left <= (double)right,
                                                                        (BinaryOperator.GreaterThan, SucoDecimalType) => (double)left> (double) right,
            (BinaryOperator.GreaterThanOrEqual, SucoDecimalType) => (double)left >= (double)right,
            (BinaryOperator.Plus, SucoDecimalType) => (double)left + (double)right,
            (BinaryOperator.Minus, SucoDecimalType) => (double)left - (double)right,
            (BinaryOperator.Times, SucoDecimalType) => (double)left * (double)right,
            (BinaryOperator.Modulo, SucoDecimalType) => ((double)left % (double)right + (double)right) % (double)right,
            (BinaryOperator.Divide, SucoDecimalType) => (double)left / (double)right,
            (BinaryOperator.Power, SucoDecimalType) => Math.Pow((double)left, (double)right),

            // Decimal op Int
            (BinaryOperator.Equal, SucoIntegerType) => (double)left == (int)right,
            (BinaryOperator.NotEqual, SucoIntegerType) => (double)left != (int)right,
            (BinaryOperator.LessThan, SucoIntegerType) => (double)left <(int)right,
                                                                        (BinaryOperator.LessThanOrEqual, SucoIntegerType) => (double)left <= (int)right,
                                                                        (BinaryOperator.GreaterThan, SucoIntegerType) => (double)left> (int) right,
            (BinaryOperator.GreaterThanOrEqual, SucoIntegerType) => (double)left >= (int)right,
            (BinaryOperator.Plus, SucoIntegerType) => (double)left + (int)right,
            (BinaryOperator.Minus, SucoIntegerType) => (double)left - (int)right,
            (BinaryOperator.Times, SucoIntegerType) => (double)left * (int)right,
            (BinaryOperator.Modulo, SucoIntegerType) => ((double)left % (int)right + (int)right) % (int)right,
            (BinaryOperator.Divide, SucoIntegerType) => (double)left / (int)right,
            (BinaryOperator.Power, SucoIntegerType) => Math.Pow((double)left, (int)right),

            _ => base.InterpretBinaryOperator(left, op, rightType, right),
        };
Exemplo n.º 13
0
 public override bool Equals(SucoType other) => other is SucoDecimalType;
Exemplo n.º 14
0
 public override bool Equals(SucoType other) => other is SucoCellType;
Exemplo n.º 15
0
 public override bool Equals(SucoType other) => other is SucoStringType;
Exemplo n.º 16
0
 public SucoArrayExpression(int startIndex, int endIndex, List <SucoExpression> elements, SucoType type = null)
     : base(startIndex, endIndex, type)
 {
     Elements = elements;
 }
Exemplo n.º 17
0
 public SucoStringLiteralExpression(int startIndex, int endIndex, SucoStringLiteralPiece[] pieces, SucoType type = null)
     : base(startIndex, endIndex, type)
 {
     Pieces = pieces;
 }
Exemplo n.º 18
0
 public SucoExpression ImplicitlyConvertTo(SucoType type) =>
 Type.Equals(type) ? this :
 Type.ImplicitlyConvertibleTo(type) ? new SucoImplicitConversionExpression(StartIndex, EndIndex, this, type) :
 throw new InvalidOperationException("Unexpected implicit conversion. Call Type.ImplicitlyConvertibleTo first to ensure convertibility.");
Exemplo n.º 19
0
        public static SucoExpression ParseCode(string source, SucoTypeEnvironment env, SucoContext context, SucoType expectedResultType = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }

            try
            {
                // Try parsing as a standalone expression (e.g. “cells.unique”).
                var parser = new SucoParser(source, context);
                var ret    = parser.parseExpression();
                parser.EnforceEof();
                ret = ret.DeduceTypes(env, context);
                if (expectedResultType != null && !ret.Type.ImplicitlyConvertibleTo(expectedResultType))
                {
                    throw new SucoParseException($"The expression is of type “{ret.Type}”, which is not implicitly convertible to the required type, “{expectedResultType}”.", ret.StartIndex, ret.EndIndex);
                }
                return(expectedResultType == null ? ret : ret.ImplicitlyConvertTo(expectedResultType));
            }
            catch (SucoParseException pe1)
            {
                try
                {
                    // Try parsing as a list comprehension (e.g. “a: a.odd”).
                    var parser = new SucoParser(source, context);
                    var ret    = parser.parseListComprehension();
                    parser.EnforceEof();
                    ret = ret.DeduceTypes(env, context);
                    if (expectedResultType != null && !ret.Type.ImplicitlyConvertibleTo(expectedResultType))
                    {
                        throw new SucoParseException($"The expression is of type “{ret.Type}”, which is not implicitly convertible to the required type, “{expectedResultType}”.", ret.StartIndex, ret.EndIndex);
                    }
                    return(expectedResultType == null ? ret : ret.ImplicitlyConvertTo(expectedResultType));
                }
                catch (SucoParseException pe2) when(pe2.StartIndex <= pe1.StartIndex)
                {
                }
                throw;
            }
        }
Exemplo n.º 20
0
 public SucoOptimizedArrayExpression(int startIndex, int endIndex, Array constants, SucoExpression[] expressions, SucoType type)
     : base(startIndex, endIndex, type)
 {
     Constants   = constants;
     Expressions = expressions;
 }
Exemplo n.º 21
0
 public SucoExpression(int startIndex, int endIndex, SucoType type = null)
     : base(startIndex, endIndex)
 {
     Type = type;
 }
Exemplo n.º 22
0
 public override object InterpretBinaryOperator(object left, BinaryOperator @operator, SucoType rightType, object right) => (@operator, rightType) switch
 {
     (BinaryOperator.Equal, SucoBooleanType) => op((bool?)left, (bool?)right, (a, b) => a == b),
     (BinaryOperator.NotEqual, SucoBooleanType) => op((bool?)left, (bool?)right, (a, b) => a != b),
     (BinaryOperator.And, SucoBooleanType) => (bool?)left == false || (bool?)right == false ? false : left == null || right == null ? null : true,
     (BinaryOperator.Or, SucoBooleanType) => (bool?)left == true || (bool?)right == true ? true : left == null || right == null ? null : false,
     _ => base.InterpretBinaryOperator(left, @operator, rightType, right)
 };
Exemplo n.º 23
0
 public override bool Equals(SucoType other) => other is SucoBooleanType;
Exemplo n.º 24
0
 public SucoListType(SucoType elementType)
 {
     ElementType = elementType;
 }
Exemplo n.º 25
0
 public override bool Equals(SucoType other) => other is SucoIntegerType;
Exemplo n.º 26
0
 public override bool Equals(SucoType other) => other is SucoEnumType e && e.Names.SequenceEqual(Names);