Example #1
0
        protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context)
        {
            var condition = Condition.DeduceTypes(env, context);

            if (!(condition.Type is SucoBooleanType))
            {
                throw new SucoCompileException($"The condition in a ?: operator must be a boolean.", Condition.StartIndex, Condition.EndIndex);
            }

            var      trueExpr  = True.DeduceTypes(env, context);
            var      falseExpr = False.DeduceTypes(env, context);
            SucoType thisType;

            if (trueExpr.Type.Equals(falseExpr.Type))
            {
                thisType = trueExpr.Type;
            }
            else if (trueExpr.Type.ImplicitlyConvertibleTo(falseExpr.Type))
            {
                trueExpr = trueExpr.ImplicitlyConvertTo(falseExpr.Type);
                thisType = falseExpr.Type;
            }
            else if (falseExpr.Type.ImplicitlyConvertibleTo(trueExpr.Type))
            {
                falseExpr = falseExpr.ImplicitlyConvertTo(trueExpr.Type);
                thisType  = trueExpr.Type;
            }
            else
            {
                throw new SucoCompileException($"Types “{trueExpr.Type}” and “{falseExpr.Type}” are not compatible.", True.StartIndex, False.EndIndex);
            }

            return(new SucoConditionalExpression(StartIndex, EndIndex, condition, trueExpr, falseExpr, thisType));
        }
Example #2
0
        protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context)
        {
            var valueExpr = ValueExpression.DeduceTypes(env, context);
            var innerExpr = InnerExpression.DeduceTypes(env.DeclareVariable(VariableName, valueExpr.Type), context);

            return(new SucoLetExpression(StartIndex, EndIndex, VariableName, valueExpr, innerExpr, innerExpr.Type));
        }
        public override SucoListCondition DeduceTypes(SucoTypeEnvironment env, SucoContext context, SucoType elementType)
        {
            var innerExpression = Expression.DeduceTypes(env, context);

            if (!innerExpression.Type.ImplicitlyConvertibleTo(SucoType.Boolean))
            {
                throw new SucoCompileException($"A condition expression must be a boolean (or implicitly convertible to one).", StartIndex, EndIndex);
            }
            return(new SucoListExpressionCondition(StartIndex, EndIndex, innerExpression.ImplicitlyConvertTo(SucoType.Boolean)));
        }
Example #4
0
        private HttpResponse PlayWithSuco(HttpRequest req)
        {
            List <object> htmlBlocks  = null;
            var           code        = req.Post["code"].Value;
            var           environment = new SucoTypeEnvironment()
                                        // built-ins
                                        .DeclareVariable("cells", SucoType.Cell.List().List());

            if (code != null)
            {
                htmlBlocks = new List <object>();

                object exceptionBox(Exception exc, (int start, int?end)[] highlights)
Example #5
0
 protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context)
 {
     try
     {
         var type = env.GetVariableType(Name);
         if (type == null)
         {
             throw new SucoCompileException($"Unknown variable “{Name}”.", StartIndex, EndIndex);
         }
         return(new SucoIdentifierExpression(StartIndex, EndIndex, Name, type));
     }
     catch (SucoTempCompileException tc)
     {
         throw new SucoCompileException(tc.Message, StartIndex, EndIndex);
     }
 }
Example #6
0
        protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context)
        {
            var op = Operand.DeduceTypes(env, context);

            try
            {
                var resultType = op.Type.GetUnaryOperatorType(Operator);
                if (resultType == null)
                {
                    throw new SucoCompileException($"Type “{op.Type}” does not support the “{Operator}” unary operator.", StartIndex, EndIndex);
                }
                return(new SucoUnaryOperatorExpression(StartIndex, EndIndex, op, Operator, resultType));
            }
            catch (SucoTempCompileException ce)
            {
                throw new SucoCompileException(ce.Message, StartIndex, EndIndex);
            }
        }
        protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context)
        {
            var left  = Left.DeduceTypes(env, context);
            var right = Right.DeduceTypes(env, context);

            try
            {
                var resultType = left.Type.GetBinaryOperatorType(Operator, right.Type, context);
                if (resultType == null)
                {
                    throw new SucoCompileException($"Types “{left.Type}” and “{right.Type}” do not support the “{Operator}” operator.", left.StartIndex, right.EndIndex);
                }
                return(new SucoBinaryOperatorExpression(StartIndex, EndIndex, left, right, Operator, resultType));
            }
            catch (SucoTempCompileException ce)
            {
                throw new SucoCompileException(ce.Message, StartIndex, EndIndex);
            }
        }
Example #8
0
        protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context)
        {
            var op = Operand.DeduceTypes(env, context);

            try
            {
                // Special case: the “.pos” member should work on any variable from a list comprehension
                if (MemberName == "pos" && op is SucoIdentifierExpression ident && env.IsVariableInListComprehension(ident.Name))
                {
                    return(new SucoPositionExpression(ident.StartIndex, ident.EndIndex, ident.Name, SucoType.Integer));
                }

                return(new SucoMemberAccessExpression(StartIndex, EndIndex, op, MemberName, op.Type.GetMemberType(MemberName, context)));
            }
            catch (SucoTempCompileException ce)
            {
                throw new SucoCompileException(ce.Message, StartIndex, EndIndex);
            }
        }
Example #9
0
 protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context) => new SucoBooleanLiteralExpression(StartIndex, EndIndex, LiteralValue, SucoType.Boolean);
Example #10
0
 protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context) => this;
Example #11
0
        public HttpResponse PuzzlePublish(HttpRequest req)
        {
            if (req.Method != HttpMethod.Post)
            {
                return(HttpResponse.Empty(HttpStatusCode._405_MethodNotAllowed));
            }

            var jsonRaw = req.Post["puzzle"].Value;

            if (jsonRaw == null || !JsonDict.TryParse(jsonRaw, out var json))
            {
                return(HttpResponse.PlainText("The data transmitted is not valid JSON.", HttpStatusCode._400_BadRequest));
            }

            try
            {
                var puzzle = new Puzzle();

                puzzle.Title   = json["title"].GetString();
                puzzle.Author  = json["author"].GetString();
                puzzle.Rules   = json["rules"].GetString();
                puzzle.UrlName = MD5.ComputeUrlName(jsonRaw);

                var givens = json["givens"].GetList().Select((v, ix) => (v, ix)).Where(tup => tup.v != null).Select(tup => (cell: tup.ix, value: tup.v.GetInt())).ToArray();
                if (givens.Any(given => given.cell < 0 || given.cell >= 81))
                {
                    return(HttpResponse.PlainText($"At least one given is out of range (cell {puzzle.Givens.First(given => given.cell < 0 || given.cell >= 81).cell}).", HttpStatusCode._400_BadRequest));
                }
                puzzle.Givens = givens.Length > 0 ? givens : null;

                var constraints           = json["constraints"].GetList();
                var customConstraintTypes = json["customConstraintTypes"].GetList();

                using var tr = new TransactionScope(TransactionScopeOption.RequiresNew, new TransactionOptions { IsolationLevel = System.Transactions.IsolationLevel.Serializable });
                using var db = new Db();

                if (db.Puzzles.Any(p => p.UrlName == puzzle.UrlName))
                {
                    return(HttpResponse.PlainText(puzzle.UrlName));
                }

                var dbConstraintTypes = constraints.Select(c => c["type"].GetInt()).Where(c => c >= 0).Distinct().ToArray()
                                        .Apply(cIds => db.Constraints.Where(c => cIds.Contains(c.ConstraintID))).AsEnumerable().ToDictionary(c => c.ConstraintID);
                var faultyId = constraints.Select(c => c["type"].GetInt()).Where(c => c >= 0).FirstOrNull(c => !dbConstraintTypes.ContainsKey(c));
                if (faultyId != null)
                {
                    return(HttpResponse.PlainText($"Unknown constraint type ID: {faultyId.Value}.", HttpStatusCode._400_BadRequest));
                }

                // Add the custom constraint types into the database
                foreach (var constraint in constraints)
                {
                    if (constraint["type"].GetInt() is int typeId && typeId < 0 && !dbConstraintTypes.ContainsKey(typeId))
                    {
                        if (~typeId >= customConstraintTypes.Count || customConstraintTypes[~typeId] == null)
                        {
                            return(HttpResponse.PlainText($"Undefined custom constraint type: {typeId}. List has {customConstraintTypes.Count} entries.", HttpStatusCode._400_BadRequest));
                        }
                        var cType = customConstraintTypes[~typeId];
                        var kind  = EnumStrong.Parse <ConstraintKind>(cType["kind"].GetString());

                        // Some verifications:
                        // Make sure the variable types parse as valid Suco types
                        var env = new SucoTypeEnvironment();
                        foreach (var(varName, varType) in cType["variables"].GetDict())
                        {
                            if (!SucoType.TryParse(varType.GetString(), out var type))
                            {
                                return(HttpResponse.PlainText($"Unrecognized Suco type: {varType.GetString()}.", HttpStatusCode._400_BadRequest));
                            }
                            env = env.DeclareVariable(varName, type);
                        }
Example #12
0
 public abstract SucoListCondition DeduceTypes(SucoTypeEnvironment env, SucoContext context, SucoType elementType);