Bind return type from a function to a variable
This commit is contained in:
parent
dbc7b4eb4f
commit
71397f5db2
|
@ -42,5 +42,33 @@ namespace Upsilon.BaseTypes
|
|||
}
|
||||
return new GenericUserData(o);
|
||||
}
|
||||
|
||||
public static Type GetLuaType(object o)
|
||||
{
|
||||
if (o is ScriptType t)
|
||||
{
|
||||
return t.Type;
|
||||
}
|
||||
|
||||
switch (o)
|
||||
{
|
||||
case bool _:
|
||||
return Type.Boolean;
|
||||
case int _:
|
||||
return Type.Number;
|
||||
case long _:
|
||||
return Type.Number;
|
||||
case float _:
|
||||
return Type.Number;
|
||||
case double _:
|
||||
return Type.Number;
|
||||
case string _:
|
||||
return Type.String;
|
||||
case null:
|
||||
return Type.Nil;
|
||||
default:
|
||||
return Type.UserData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -50,7 +50,11 @@ namespace Upsilon.Binder
|
|||
}
|
||||
unboundFunctionStatement.Value.Block =
|
||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.Value.UnboundBlock);
|
||||
var resultType = Scope.ReturnType;
|
||||
Scope = Scope.ParentScope;
|
||||
var variable = (FunctionVariableSymbol)Scope.Variables[unboundFunctionStatement.Key];
|
||||
variable.IsBound = true;
|
||||
variable.ResultType = resultType;
|
||||
}
|
||||
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
|
||||
return new BoundScript((BoundBlockStatement) bound, e.Span, Scope);
|
||||
|
@ -198,6 +202,7 @@ namespace Upsilon.Binder
|
|||
parameters.Add(bound);
|
||||
}
|
||||
|
||||
var returnType = Type.Unknown;
|
||||
if (expression.Kind == BoundKind.VariableExpression)
|
||||
{
|
||||
var variableExpression =(BoundVariableExpression) expression;
|
||||
|
@ -216,14 +221,18 @@ namespace Upsilon.Binder
|
|||
var unboundFunctionStatement = _unboundFunctions[function.Name];
|
||||
unboundFunctionStatement.Block =
|
||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock);
|
||||
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);
|
||||
return new BoundFunctionCallExpression(expression, parameters.ToImmutable(), e.Span, returnType);
|
||||
}
|
||||
|
||||
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
|
||||
|
@ -402,9 +411,10 @@ namespace Upsilon.Binder
|
|||
{
|
||||
Scope = innerScope;
|
||||
var block = BindBlockStatement(e.Block);
|
||||
var returnType = Scope.ReturnType;
|
||||
Scope = Scope.ParentScope;
|
||||
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span,
|
||||
innerScope);
|
||||
innerScope, returnType);
|
||||
return func;
|
||||
}
|
||||
else
|
||||
|
@ -445,7 +455,7 @@ namespace Upsilon.Binder
|
|||
|
||||
if (!Scope.TryGetVariable(name, !isLocal, out var variable))
|
||||
{
|
||||
var functionVariable = new FunctionVariableSymbol(name, Type.Function, isLocal, parameters.ToImmutable())
|
||||
var functionVariable = new FunctionVariableSymbol(name, isLocal, parameters.ToImmutable(), func.ReturnType)
|
||||
{
|
||||
CommentValue = commentData.ToArray()
|
||||
};
|
||||
|
@ -480,6 +490,17 @@ namespace Upsilon.Binder
|
|||
private BoundStatement BindReturnStatement(ReturnStatementSyntax e)
|
||||
{
|
||||
var expression = BindExpression(e.Expression);
|
||||
if (expression.Type != Type.Unknown && expression.Type != Type.Unknown &&
|
||||
Scope.ReturnType != Type.Unknown && Scope.ReturnType != Type.Nil)
|
||||
{
|
||||
if (expression.Type != Scope.ReturnType)
|
||||
{
|
||||
_diagnostics.LogError($"Can't return type '{expression.Type}' from this scope, earlier in the" +
|
||||
$" scope a return type of '{Scope.ReturnType}' is defined.", e.Span);
|
||||
}
|
||||
}
|
||||
if (expression.Type != Type.Unknown && expression.Type != Type.Nil)
|
||||
Scope.ReturnType = expression.Type;
|
||||
return new BoundReturnStatement(expression, e.Span);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,10 +11,11 @@ namespace Upsilon.Binder
|
|||
public ImmutableArray<BoundExpression> Parameters { get; }
|
||||
|
||||
public BoundFunctionCallExpression(BoundExpression identifier, ImmutableArray<BoundExpression> parameters,
|
||||
TextSpan span) : base(span)
|
||||
TextSpan span, Type type) : base(span)
|
||||
{
|
||||
Identifier = identifier;
|
||||
Parameters = parameters;
|
||||
Type = type;
|
||||
}
|
||||
|
||||
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
||||
|
@ -37,6 +38,6 @@ namespace Upsilon.Binder
|
|||
yield return this;
|
||||
}
|
||||
|
||||
public override Type Type => Type.Unknown;
|
||||
public override Type Type { get; }
|
||||
}
|
||||
}
|
|
@ -10,12 +10,13 @@ namespace Upsilon.Binder
|
|||
public ImmutableArray<BoundVariableSymbol> Parameters { get; }
|
||||
public BoundBlockStatement Block { get; set; }
|
||||
|
||||
public BoundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block, TextSpan span,
|
||||
BoundScope scope) : base(span)
|
||||
public BoundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block,
|
||||
TextSpan span, BoundScope scope, Type returnType) : base(span)
|
||||
{
|
||||
Parameters = parameters;
|
||||
Block = block;
|
||||
Scope = scope;
|
||||
ReturnType = returnType;
|
||||
}
|
||||
|
||||
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
||||
|
@ -35,5 +36,6 @@ namespace Upsilon.Binder
|
|||
|
||||
public override Type Type => Type.Function;
|
||||
public BoundScope Scope { get; set; }
|
||||
public Type ReturnType { get; }
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Type = Upsilon.BaseTypes.Type;
|
||||
|
||||
namespace Upsilon.Binder
|
||||
{
|
||||
|
@ -8,6 +9,7 @@ namespace Upsilon.Binder
|
|||
public readonly BoundScope ParentScope;
|
||||
public BoundScope ReadOnlyScope { get; private set; }
|
||||
public readonly Dictionary<string, VariableSymbol> Variables;
|
||||
public Type ReturnType { get; set; } = Type.Nil;
|
||||
|
||||
public BoundScope(BoundScope parentScope)
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using Upsilon.BaseTypes;
|
||||
using Upsilon.Parser;
|
||||
using Upsilon.Text;
|
||||
|
||||
|
@ -8,7 +9,8 @@ namespace Upsilon.Binder
|
|||
public class UnboundFunctionExpression : BoundFunctionExpression
|
||||
{
|
||||
public UnboundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters,
|
||||
BlockStatementSyntax unboundBlock, TextSpan span, BoundScope scope) : base(parameters, null, span, scope)
|
||||
BlockStatementSyntax unboundBlock, TextSpan span, BoundScope scope)
|
||||
: base(parameters, null, span, scope, Type.Unknown)
|
||||
{
|
||||
UnboundBlock = unboundBlock;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,14 @@ namespace Upsilon.Binder
|
|||
public class FunctionVariableSymbol : VariableSymbol
|
||||
{
|
||||
public ImmutableArray<VariableSymbol> Parameters { get; }
|
||||
public Type ResultType { get; internal set; }
|
||||
public bool IsBound { get; set; }
|
||||
|
||||
public FunctionVariableSymbol(string name, Type type, bool local, ImmutableArray<VariableSymbol> parameters)
|
||||
: base(name, type, local)
|
||||
public FunctionVariableSymbol(string name, bool local, ImmutableArray<VariableSymbol> parameters, Type resultType)
|
||||
: base(name, Type.Function, local)
|
||||
{
|
||||
Parameters = parameters;
|
||||
ResultType = resultType;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -46,8 +46,8 @@ namespace Upsilon.StandardLibraries
|
|||
var boundScope =
|
||||
new BoundScope(
|
||||
scope.Variables.ToDictionary(x => x.Key,
|
||||
x => (VariableSymbol) new FunctionVariableSymbol(x.Key, x.Value.Type, false,
|
||||
ImmutableArray<VariableSymbol>.Empty) {IsBound = true}),
|
||||
x => (VariableSymbol) new FunctionVariableSymbol(x.Key, false,
|
||||
ImmutableArray<VariableSymbol>.Empty, x.Value.Type) {IsBound = true}),
|
||||
null);
|
||||
return (scope, boundScope);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue