From 576273ac56818d5d83f5d35aae1f33c7013b27f5 Mon Sep 17 00:00:00 2001 From: Deukhoofd Date: Wed, 28 Nov 2018 13:30:24 +0100 Subject: [PATCH] Better support for binding functions, specifically nested functions --- Upsilon/Binder/Binder.cs | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/Upsilon/Binder/Binder.cs b/Upsilon/Binder/Binder.cs index 836cee2..0feac07 100644 --- a/Upsilon/Binder/Binder.cs +++ b/Upsilon/Binder/Binder.cs @@ -192,7 +192,8 @@ namespace Upsilon.Binder if (expression.Type != Type.Function && expression.Type != Type.Unknown) { //TODO Better error - throw new Exception(); + _diagnostics.LogError($"Unknown function called.", e.Span); + return new BoundLiteralExpression(new ScriptNull(), e.Span); } var parameters = ImmutableArray.CreateBuilder(); @@ -203,10 +204,8 @@ namespace Upsilon.Binder } var returnType = Type.Unknown; - if (expression.Kind == BoundKind.VariableExpression) + if (ResolveVariable(expression) is FunctionVariableSymbol function) { - var variableExpression =(BoundVariableExpression) expression; - var function = (FunctionVariableSymbol)variableExpression.Variable.VariableSymbol; if (!function.IsBound) { Scope = new BoundScope(Scope); @@ -221,20 +220,38 @@ namespace Upsilon.Binder var unboundFunctionStatement = _unboundFunctions[function.Name]; unboundFunctionStatement.Block = (BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock); - returnType = Scope.ReturnType; - Scope = Scope.ParentScope; - function.IsBound = true; + returnType = Scope.ReturnType; + Scope = Scope.ParentScope; + function.IsBound = true; function.ResultType = returnType; _unboundFunctions.Remove(function.Name); } returnType = function.ResultType; + } //TODO: validate parameters return new BoundFunctionCallExpression(expression, parameters.ToImmutable(), e.Span, returnType); } + private VariableSymbol ResolveVariable(BoundExpression expression) + { + if (expression.Kind == BoundKind.VariableExpression) + { + var variableExpression = (BoundVariableExpression) expression; + return variableExpression.Variable.VariableSymbol; + } + if (expression.Kind == BoundKind.BoundFullstopIndexExpression) + { + var fullStopIndexExpression = (BoundFullStopIndexExpression) expression; + var indexerExpression = fullStopIndexExpression.Expression; + var indexerVariable = (TableVariableSymbol)ResolveVariable(indexerExpression); + return indexerVariable.Variables[fullStopIndexExpression.Index]; + } + return null; + } + private BoundExpression BindVariableExpression(VariableExpressionSyntax e) { var name = e.Identifier.Name; @@ -461,6 +478,7 @@ namespace Upsilon.Binder }; variable = functionVariable; functionVariable.IsBound = !(func is UnboundFunctionExpression); + functionVariable.ResultType = func.ReturnType; if (isLocal) Scope.DefineLocalVariable(variable); else