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)); }
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))); }