Bind whether a variable symbol is a creation statement or just changing the variable

This commit is contained in:
Deukhoofd 2018-12-02 17:26:23 +01:00
parent 07a71129a2
commit a9f4ef1b65
No known key found for this signature in database
GPG Key ID: B4C087AC81641654
2 changed files with 21 additions and 15 deletions

View File

@ -283,7 +283,7 @@ namespace Upsilon.Binder
_diagnostics.LogUnknownVariable(e.Identifier.Span, name); _diagnostics.LogUnknownVariable(e.Identifier.Span, name);
return new BoundLiteralExpression(new ScriptNull(), e.Span); return new BoundLiteralExpression(new ScriptNull(), e.Span);
} }
var boundVariable = new BoundVariableSymbol(variable, e.Identifier.Span); var boundVariable = new BoundVariableSymbol(variable, false, e.Identifier.Span);
return new BoundVariableExpression(boundVariable, e.Span); return new BoundVariableExpression(boundVariable, e.Span);
} }
@ -293,10 +293,11 @@ namespace Upsilon.Binder
return new BoundExpressionStatement(exp, s.Span); return new BoundExpressionStatement(exp, s.Span);
} }
private VariableSymbol TryBindVariable(string name, bool isLocal, BoundExpression assignment, string[] commentData) private (VariableSymbol Symbol, bool IsCreation) TryBindVariable(string name, bool isLocal, BoundExpression assignment, string[] commentData)
{ {
if (name == "_") if (name == "_")
return null; return (null, false);
var isCreation = false;
if (!Scope.TryGetVariable(name, !isLocal, out var variable)) if (!Scope.TryGetVariable(name, !isLocal, out var variable))
{ {
if (assignment.Type == Type.Table) if (assignment.Type == Type.Table)
@ -323,6 +324,8 @@ namespace Upsilon.Binder
Scope.DefineLocalVariable(variable); Scope.DefineLocalVariable(variable);
else else
Scope.AssignToNearest(variable); Scope.AssignToNearest(variable);
isCreation = true;
} }
else else
{ {
@ -347,11 +350,11 @@ namespace Upsilon.Binder
else else
{ {
_diagnostics.LogCannotConvert(assignment.Type, variable.Type, assignment.Span); _diagnostics.LogCannotConvert(assignment.Type, variable.Type, assignment.Span);
return null; return (null, false);
} }
} }
} }
return variable; return (variable, isCreation);
} }
private BoundStatement BindAssignmentStatement(AssignmentStatementSyntax e) private BoundStatement BindAssignmentStatement(AssignmentStatementSyntax e)
@ -363,14 +366,15 @@ namespace Upsilon.Binder
var boundExpression = BindExpression(e.Expression); var boundExpression = BindExpression(e.Expression);
var isLocal = e.LocalToken != null; var isLocal = e.LocalToken != null;
var boundVariable = TryBindVariable(name, isLocal, boundExpression, e.CommentData); var (symbol, isCreation) = TryBindVariable(name, isLocal, boundExpression, e.CommentData);
if (boundVariable != null) if (symbol != null)
{ {
if (boundVariable.Type == Type.Unknown) if (symbol.Type == Type.Unknown)
{ {
_diagnostics.LogUnknownVariableType(boundVariable.Name, variableExpression.Span); _diagnostics.LogUnknownVariableType(symbol.Name, variableExpression.Span);
} }
var variable = new BoundVariableSymbol(boundVariable, variableExpression.Span);
var variable = new BoundVariableSymbol(symbol, isCreation, variableExpression.Span);
return new BoundVariableAssignment(variable, boundExpression, isLocal, e.Span); return new BoundVariableAssignment(variable, boundExpression, isLocal, e.Span);
} }
} }
@ -387,11 +391,11 @@ namespace Upsilon.Binder
foreach (var identifierToken in s.Identifiers) foreach (var identifierToken in s.Identifiers)
{ {
var boundVariable = TryBindVariable(identifierToken.Name, isLocal, assignment, null); var boundVariable = TryBindVariable(identifierToken.Name, isLocal, assignment, null);
if (boundVariable.Type == Type.Unknown) if (boundVariable.Symbol.Type == Type.Unknown)
{ {
_diagnostics.LogUnknownVariableType(boundVariable.Name, identifierToken.Span); _diagnostics.LogUnknownVariableType(boundVariable.Symbol.Name, identifierToken.Span);
} }
ls.Add(boundVariable); ls.Add(boundVariable.Symbol);
} }
return new BoundMultiAssignmentStatement(ls.ToImmutableArray(), assignment, s.Span); return new BoundMultiAssignmentStatement(ls.ToImmutableArray(), assignment, s.Span);
} }
@ -461,7 +465,7 @@ namespace Upsilon.Binder
{ {
variableSymbol = new FunctionParameterSymbol(variable.IdentifierName.Name, Type.Unknown); variableSymbol = new FunctionParameterSymbol(variable.IdentifierName.Name, Type.Unknown);
} }
parameters.Add(new BoundVariableSymbol(variableSymbol, identifierToken.Span)); parameters.Add(new BoundVariableSymbol(variableSymbol, true, identifierToken.Span));
innerScope.DefineLocalVariable(variableSymbol); innerScope.DefineLocalVariable(variableSymbol);
} }

View File

@ -7,13 +7,15 @@ namespace Upsilon.Binder
{ {
public class BoundVariableSymbol : BoundExpression public class BoundVariableSymbol : BoundExpression
{ {
public BoundVariableSymbol(VariableSymbol variableSymbol, TextSpan span) : base(span) public BoundVariableSymbol(VariableSymbol variableSymbol, bool isCreation, TextSpan span) : base(span)
{ {
VariableSymbol = variableSymbol; VariableSymbol = variableSymbol;
IsCreation = isCreation;
} }
public VariableSymbol VariableSymbol { get; } public VariableSymbol VariableSymbol { get; }
public bool IsCreation { get; }
public override BoundKind Kind => BoundKind.BoundVariableSymbol; public override BoundKind Kind => BoundKind.BoundVariableSymbol;
public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition) public override IEnumerable<BoundNode> GetNodeAtPosition(int characterPosition)
{ {