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)); }
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))); }
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)
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); } }
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); } }
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); } }
protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context) => new SucoBooleanLiteralExpression(StartIndex, EndIndex, LiteralValue, SucoType.Boolean);
protected override SucoExpression deduceTypes(SucoTypeEnvironment env, SucoContext context) => this;
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); }
public abstract SucoListCondition DeduceTypes(SucoTypeEnvironment env, SucoContext context, SucoType elementType);