Example #1
0
 public Binder(DiagnosticsReport diagnostics, SymbolTable symbols)
     : base(diagnostics, symbols)
 {
     exprBinder = new ExpressionBinder(Symbols, Diagnostics);
 }
        internal static Expression BindVariables(Expression e)
        {
            ExpressionBinder eb = new ExpressionBinder();

            return(eb.Visit(e));
        }
Example #3
0
            private void ResolveConstants()
            {
                var exprBinder = new ExpressionBinder(Symbols, new DiagnosticsReport(Diagnostics.FilePath));

                while (constantsToResolve.Count > 0)
                {
                    var c = constantsToResolve.Dequeue();
                    if (!IsExprConstant(c.Constant, c.Initializer))
                    {
                        continue;
                    }

                    var constantInitializer = exprBinder.Visit(c.Initializer) !;
                    if (constantInitializer.IsInvalid)
                    {
                        constantsToResolve.Enqueue(c); // try again
                    }
                    else
                    {
                        var numUnresolved = CountUnresolvedDependencies(constantInitializer);
                        if (numUnresolved == 0)
                        {
                            // reduce the initializer to a literal
                            c.Constant.Initializer = ((BasicType)constantInitializer.Type !).TypeCode switch
                            {
                                BasicTypeCode.Bool => new BoundBoolLiteralExpression(Evaluator.Evaluate(constantInitializer)[0].AsUInt64 == 1),
                                BasicTypeCode.Int => new BoundIntLiteralExpression(Evaluator.Evaluate(constantInitializer)[0].AsInt32),
                                BasicTypeCode.Float => new BoundFloatLiteralExpression(Evaluator.Evaluate(constantInitializer)[0].AsFloat),
                                BasicTypeCode.String => constantInitializer, // if it is a STRING it should already be a literal
                                _ => throw new System.InvalidOperationException(),
                            };
                        }
                        else
                        {
                            if (numUnresolved < c.NumUnresolved)
                            {
                                constantsToResolve.Enqueue((c.Constant, c.Initializer, numUnresolved)); // try again
                            }
                            else
                            {
                                Diagnostics.AddError($"The constant '{c.Constant.Name}' involves a circular definition", c.Initializer.Source);
                            }
                        }
                    }
                }

                bool IsExprConstant(VariableSymbol targetConstant, Expression expr)
                {
                    if (expr is IdentifierExpression idExpr)
                    {
                        switch (Symbols.Lookup(idExpr.Identifier))
                        {
                        case VariableSymbol v when !v.IsConstant:
                            Diagnostics.AddError($"The expression assigned to '{targetConstant.Name}' must be constant. The variable '{idExpr.Identifier}' is not constant", idExpr.Source);
                            return(false);

                        case null:
                            Diagnostics.AddError($"Unknown symbol '{idExpr.Identifier}'", idExpr.Source);
                            return(false);
                        }
                    }

                    return(expr.Children.Where(c => c is Expression).All(e => IsExprConstant(targetConstant, (Expression)e)));
                }