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);
|
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 =
|
unboundFunctionStatement.Value.Block =
|
||||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.Value.UnboundBlock);
|
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.Value.UnboundBlock);
|
||||||
|
var resultType = Scope.ReturnType;
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
|
var variable = (FunctionVariableSymbol)Scope.Variables[unboundFunctionStatement.Key];
|
||||||
|
variable.IsBound = true;
|
||||||
|
variable.ResultType = resultType;
|
||||||
}
|
}
|
||||||
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
|
_unboundFunctions = new Dictionary<string, UnboundFunctionExpression>();
|
||||||
return new BoundScript((BoundBlockStatement) bound, e.Span, Scope);
|
return new BoundScript((BoundBlockStatement) bound, e.Span, Scope);
|
||||||
|
@ -198,6 +202,7 @@ namespace Upsilon.Binder
|
||||||
parameters.Add(bound);
|
parameters.Add(bound);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var returnType = Type.Unknown;
|
||||||
if (expression.Kind == BoundKind.VariableExpression)
|
if (expression.Kind == BoundKind.VariableExpression)
|
||||||
{
|
{
|
||||||
var variableExpression =(BoundVariableExpression) expression;
|
var variableExpression =(BoundVariableExpression) expression;
|
||||||
|
@ -216,14 +221,18 @@ namespace Upsilon.Binder
|
||||||
var unboundFunctionStatement = _unboundFunctions[function.Name];
|
var unboundFunctionStatement = _unboundFunctions[function.Name];
|
||||||
unboundFunctionStatement.Block =
|
unboundFunctionStatement.Block =
|
||||||
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock);
|
(BoundBlockStatement) BindBlockStatement(unboundFunctionStatement.UnboundBlock);
|
||||||
|
returnType = Scope.ReturnType;
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
function.IsBound = true;
|
function.IsBound = true;
|
||||||
|
function.ResultType = returnType;
|
||||||
_unboundFunctions.Remove(function.Name);
|
_unboundFunctions.Remove(function.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
returnType = function.ResultType;
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO: validate parameters
|
//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)
|
private BoundExpression BindVariableExpression(VariableExpressionSyntax e)
|
||||||
|
@ -402,9 +411,10 @@ namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
Scope = innerScope;
|
Scope = innerScope;
|
||||||
var block = BindBlockStatement(e.Block);
|
var block = BindBlockStatement(e.Block);
|
||||||
|
var returnType = Scope.ReturnType;
|
||||||
Scope = Scope.ParentScope;
|
Scope = Scope.ParentScope;
|
||||||
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span,
|
var func = new BoundFunctionExpression(parameters.ToImmutable(), (BoundBlockStatement) block, e.Span,
|
||||||
innerScope);
|
innerScope, returnType);
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -445,7 +455,7 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
if (!Scope.TryGetVariable(name, !isLocal, out var variable))
|
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()
|
CommentValue = commentData.ToArray()
|
||||||
};
|
};
|
||||||
|
@ -480,6 +490,17 @@ namespace Upsilon.Binder
|
||||||
private BoundStatement BindReturnStatement(ReturnStatementSyntax e)
|
private BoundStatement BindReturnStatement(ReturnStatementSyntax e)
|
||||||
{
|
{
|
||||||
var expression = BindExpression(e.Expression);
|
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);
|
return new BoundReturnStatement(expression, e.Span);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,11 @@ namespace Upsilon.Binder
|
||||||
public ImmutableArray<BoundExpression> Parameters { get; }
|
public ImmutableArray<BoundExpression> Parameters { get; }
|
||||||
|
|
||||||
public BoundFunctionCallExpression(BoundExpression identifier, ImmutableArray<BoundExpression> parameters,
|
public BoundFunctionCallExpression(BoundExpression identifier, ImmutableArray<BoundExpression> parameters,
|
||||||
TextSpan span) : base(span)
|
TextSpan span, Type type) : base(span)
|
||||||
{
|
{
|
||||||
Identifier = identifier;
|
Identifier = identifier;
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
|
Type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
public override BoundKind Kind => BoundKind.BoundFunctionCallExpression;
|
||||||
|
@ -37,6 +38,6 @@ namespace Upsilon.Binder
|
||||||
yield return this;
|
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 ImmutableArray<BoundVariableSymbol> Parameters { get; }
|
||||||
public BoundBlockStatement Block { get; set; }
|
public BoundBlockStatement Block { get; set; }
|
||||||
|
|
||||||
public BoundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block, TextSpan span,
|
public BoundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters, BoundBlockStatement block,
|
||||||
BoundScope scope) : base(span)
|
TextSpan span, BoundScope scope, Type returnType) : base(span)
|
||||||
{
|
{
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
Block = block;
|
Block = block;
|
||||||
Scope = scope;
|
Scope = scope;
|
||||||
|
ReturnType = returnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
public override BoundKind Kind => BoundKind.BoundFunctionExpression;
|
||||||
|
@ -35,5 +36,6 @@ namespace Upsilon.Binder
|
||||||
|
|
||||||
public override Type Type => Type.Function;
|
public override Type Type => Type.Function;
|
||||||
public BoundScope Scope { get; set; }
|
public BoundScope Scope { get; set; }
|
||||||
|
public Type ReturnType { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Type = Upsilon.BaseTypes.Type;
|
||||||
|
|
||||||
namespace Upsilon.Binder
|
namespace Upsilon.Binder
|
||||||
{
|
{
|
||||||
|
@ -8,6 +9,7 @@ namespace Upsilon.Binder
|
||||||
public readonly BoundScope ParentScope;
|
public readonly BoundScope ParentScope;
|
||||||
public BoundScope ReadOnlyScope { get; private set; }
|
public BoundScope ReadOnlyScope { get; private set; }
|
||||||
public readonly Dictionary<string, VariableSymbol> Variables;
|
public readonly Dictionary<string, VariableSymbol> Variables;
|
||||||
|
public Type ReturnType { get; set; } = Type.Nil;
|
||||||
|
|
||||||
public BoundScope(BoundScope parentScope)
|
public BoundScope(BoundScope parentScope)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
|
using Upsilon.BaseTypes;
|
||||||
using Upsilon.Parser;
|
using Upsilon.Parser;
|
||||||
using Upsilon.Text;
|
using Upsilon.Text;
|
||||||
|
|
||||||
|
@ -8,7 +9,8 @@ namespace Upsilon.Binder
|
||||||
public class UnboundFunctionExpression : BoundFunctionExpression
|
public class UnboundFunctionExpression : BoundFunctionExpression
|
||||||
{
|
{
|
||||||
public UnboundFunctionExpression(ImmutableArray<BoundVariableSymbol> parameters,
|
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;
|
UnboundBlock = unboundBlock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,12 +23,14 @@ namespace Upsilon.Binder
|
||||||
public class FunctionVariableSymbol : VariableSymbol
|
public class FunctionVariableSymbol : VariableSymbol
|
||||||
{
|
{
|
||||||
public ImmutableArray<VariableSymbol> Parameters { get; }
|
public ImmutableArray<VariableSymbol> Parameters { get; }
|
||||||
|
public Type ResultType { get; internal set; }
|
||||||
public bool IsBound { get; set; }
|
public bool IsBound { get; set; }
|
||||||
|
|
||||||
public FunctionVariableSymbol(string name, Type type, bool local, ImmutableArray<VariableSymbol> parameters)
|
public FunctionVariableSymbol(string name, bool local, ImmutableArray<VariableSymbol> parameters, Type resultType)
|
||||||
: base(name, type, local)
|
: base(name, Type.Function, local)
|
||||||
{
|
{
|
||||||
Parameters = parameters;
|
Parameters = parameters;
|
||||||
|
ResultType = resultType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -46,8 +46,8 @@ namespace Upsilon.StandardLibraries
|
||||||
var boundScope =
|
var boundScope =
|
||||||
new BoundScope(
|
new BoundScope(
|
||||||
scope.Variables.ToDictionary(x => x.Key,
|
scope.Variables.ToDictionary(x => x.Key,
|
||||||
x => (VariableSymbol) new FunctionVariableSymbol(x.Key, x.Value.Type, false,
|
x => (VariableSymbol) new FunctionVariableSymbol(x.Key, false,
|
||||||
ImmutableArray<VariableSymbol>.Empty) {IsBound = true}),
|
ImmutableArray<VariableSymbol>.Empty, x.Value.Type) {IsBound = true}),
|
||||||
null);
|
null);
|
||||||
return (scope, boundScope);
|
return (scope, boundScope);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue