More types
This commit is contained in:
parent
3f494cef6d
commit
3bc8ef0d7d
@ -116,7 +116,7 @@ namespace Parser.Binding
|
|||||||
TokenKind.ExpressionStatement =>
|
TokenKind.ExpressionStatement =>
|
||||||
BindExpressionStatement((ExpressionStatementSyntaxNode)node),
|
BindExpressionStatement((ExpressionStatementSyntaxNode)node),
|
||||||
TokenKind.ForStatement =>
|
TokenKind.ForStatement =>
|
||||||
BindForStatement((ForStatementSyntaxNode)node),
|
BindForStatement((ForStatementSyntaxNode)node)!,
|
||||||
TokenKind.FunctionDeclaration =>
|
TokenKind.FunctionDeclaration =>
|
||||||
BindFunctionDeclaration((FunctionDeclarationSyntaxNode)node),
|
BindFunctionDeclaration((FunctionDeclarationSyntaxNode)node),
|
||||||
TokenKind.IfStatement =>
|
TokenKind.IfStatement =>
|
||||||
@ -265,9 +265,29 @@ namespace Parser.Binding
|
|||||||
return new ParameterSymbol(parameter.Text);
|
return new ParameterSymbol(parameter.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundForStatement BindForStatement(ForStatementSyntaxNode node)
|
private BoundForStatement? BindForStatement(ForStatementSyntaxNode node)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
var loopVariable = BindLoopVariable(node.Assignment.Lhs);
|
||||||
|
if (loopVariable is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var loopedExpression = BindExpression(node.Assignment.Rhs);
|
||||||
|
var body = BindStatement(node.Body);
|
||||||
|
return ForStatement(node, loopVariable, loopedExpression, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoundIdentifierNameExpression? BindLoopVariable(ExpressionSyntaxNode node)
|
||||||
|
{
|
||||||
|
if (node.Kind != TokenKind.IdentifierNameExpression)
|
||||||
|
{
|
||||||
|
_diagnostics.ReportForLoopWithoutVariable(
|
||||||
|
new TextSpan(node.Position, node.FullWidth));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Identifier(node, ((IdentifierNameExpressionSyntaxNode)node).Name.Text);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node)
|
private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node)
|
||||||
@ -342,11 +362,37 @@ namespace Parser.Binding
|
|||||||
return Assignment(node, left, right);
|
return Assignment(node, left, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BoundExpression BindConversion(BoundExpression expression, TypeSymbol targetType)
|
||||||
|
{
|
||||||
|
var conversion = Conversion.Classify(expression.Type, targetType);
|
||||||
|
if (!conversion.Exists)
|
||||||
|
{
|
||||||
|
return new BoundErrorExpression(expression.Syntax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversion.IsIdentity)
|
||||||
|
{
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Conversion(expression.Syntax, targetType, expression);
|
||||||
|
}
|
||||||
|
|
||||||
private BoundBinaryOperationExpression BindBinaryOperationExpression(BinaryOperationExpressionSyntaxNode node)
|
private BoundBinaryOperationExpression BindBinaryOperationExpression(BinaryOperationExpressionSyntaxNode node)
|
||||||
{
|
{
|
||||||
var left = BindExpression(node.Lhs);
|
var left = BindExpression(node.Lhs);
|
||||||
var right = BindExpression(node.Rhs);
|
var right = BindExpression(node.Rhs);
|
||||||
return BinaryOperation(node, left, node.Operation.Kind, right);
|
var op = BoundBinaryOperator.GetOperator(node.Operation.Kind, left.Type, right.Type);
|
||||||
|
if (op is null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Unknown binary operator '{node.Operation.Kind}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return BinaryOperation(
|
||||||
|
node,
|
||||||
|
BindConversion(left, op.Left),
|
||||||
|
op,
|
||||||
|
BindConversion(right, op.Right));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundCellArrayElementAccessExpression BindCellArrayElementAccessExpression(CellArrayElementAccessExpressionSyntaxNode node)
|
private BoundCellArrayElementAccessExpression BindCellArrayElementAccessExpression(CellArrayElementAccessExpressionSyntaxNode node)
|
||||||
@ -416,10 +462,10 @@ namespace Parser.Binding
|
|||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundNumberLiteralExpression BindNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node)
|
private BoundNumberDoubleLiteralExpression BindNumberLiteralExpression(NumberLiteralExpressionSyntaxNode node)
|
||||||
{
|
{
|
||||||
var value = (double)node.Number.Value!;
|
var value = (double)node.Number.Value!;
|
||||||
return NumberLiteral(node, value);
|
return NumberDoubleLiteral(node, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntaxNode node)
|
private BoundExpression BindParenthesizedExpression(ParenthesizedExpressionSyntaxNode node)
|
||||||
@ -436,7 +482,16 @@ namespace Parser.Binding
|
|||||||
private BoundUnaryOperationExpression BindUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode node)
|
private BoundUnaryOperationExpression BindUnaryPrefixOperationExpression(UnaryPrefixOperationExpressionSyntaxNode node)
|
||||||
{
|
{
|
||||||
var operand = BindExpression(node.Operand);
|
var operand = BindExpression(node.Operand);
|
||||||
return UnaryOperation(node, node.Operation.Kind, operand);
|
var op = BoundUnaryOperator.GetOperator(node.Operation.Kind, operand.Type);
|
||||||
|
if (op is null)
|
||||||
|
{
|
||||||
|
throw new Exception($"Unknown binary operator '{node.Operation.Kind}'.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return UnaryOperation(
|
||||||
|
node,
|
||||||
|
op,
|
||||||
|
BindConversion(operand, op.Result));
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundUnaryOperationExpression BindUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node)
|
private BoundUnaryOperationExpression BindUnaryPostfixOperationExpression(UnaryPostfixOperationExpressionSyntaxNode node)
|
||||||
|
@ -4,45 +4,164 @@ namespace Parser.Binding
|
|||||||
{
|
{
|
||||||
public class BoundBinaryOperator
|
public class BoundBinaryOperator
|
||||||
{
|
{
|
||||||
private static BoundBinaryOperator[] _operators =
|
private static BoundBinaryOperator[] _specificOperators =
|
||||||
{
|
{
|
||||||
new BoundBinaryOperator(TokenKind.EqualsToken, BoundBinaryOperatorKind.Equals),
|
new BoundBinaryOperator(
|
||||||
new BoundBinaryOperator(TokenKind.PipePipeToken, BoundBinaryOperatorKind.PipePipe),
|
TokenKind.LessToken,
|
||||||
new BoundBinaryOperator(TokenKind.AmpersandAmpersandToken, BoundBinaryOperatorKind.AmpersandAmpersand),
|
BoundBinaryOperatorKind.Less,
|
||||||
new BoundBinaryOperator(TokenKind.PipeToken, BoundBinaryOperatorKind.Pipe),
|
TypeSymbol.Int,
|
||||||
new BoundBinaryOperator(TokenKind.AmpersandToken, BoundBinaryOperatorKind.Ampersand),
|
TypeSymbol.Boolean),
|
||||||
new BoundBinaryOperator(TokenKind.LessToken, BoundBinaryOperatorKind.Less),
|
new BoundBinaryOperator(
|
||||||
new BoundBinaryOperator(TokenKind.LessOrEqualsToken, BoundBinaryOperatorKind.LessOrEquals),
|
TokenKind.PlusToken,
|
||||||
new BoundBinaryOperator(TokenKind.GreaterToken, BoundBinaryOperatorKind.Greater),
|
BoundBinaryOperatorKind.Plus,
|
||||||
new BoundBinaryOperator(TokenKind.GreaterOrEqualsToken, BoundBinaryOperatorKind.GreaterOrEquals),
|
TypeSymbol.Int),
|
||||||
new BoundBinaryOperator(TokenKind.EqualsEqualsToken, BoundBinaryOperatorKind.EqualsEquals),
|
|
||||||
new BoundBinaryOperator(TokenKind.TildeEqualsToken, BoundBinaryOperatorKind.TildeEquals),
|
|
||||||
new BoundBinaryOperator(TokenKind.ColonToken, BoundBinaryOperatorKind.Colon),
|
|
||||||
new BoundBinaryOperator(TokenKind.PlusToken, BoundBinaryOperatorKind.Plus),
|
|
||||||
new BoundBinaryOperator(TokenKind.MinusToken, BoundBinaryOperatorKind.Minus),
|
|
||||||
new BoundBinaryOperator(TokenKind.StarToken, BoundBinaryOperatorKind.Star),
|
|
||||||
new BoundBinaryOperator(TokenKind.DotStarToken, BoundBinaryOperatorKind.DotStar),
|
|
||||||
new BoundBinaryOperator(TokenKind.SlashToken, BoundBinaryOperatorKind.Slash),
|
|
||||||
new BoundBinaryOperator(TokenKind.DotSlashToken, BoundBinaryOperatorKind.DotSlash),
|
|
||||||
new BoundBinaryOperator(TokenKind.BackslashToken, BoundBinaryOperatorKind.Backslash),
|
|
||||||
new BoundBinaryOperator(TokenKind.DotBackslashToken, BoundBinaryOperatorKind.DotBackslash),
|
|
||||||
new BoundBinaryOperator(TokenKind.TildeToken, BoundBinaryOperatorKind.Tilde),
|
|
||||||
new BoundBinaryOperator(TokenKind.CaretToken, BoundBinaryOperatorKind.Caret),
|
|
||||||
new BoundBinaryOperator(TokenKind.DotCaretToken, BoundBinaryOperatorKind.DotCaret),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public BoundBinaryOperator(TokenKind syntaxKind, BoundBinaryOperatorKind kind)
|
private static BoundBinaryOperator[] _defaultOperators =
|
||||||
|
{
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.EqualsToken,
|
||||||
|
BoundBinaryOperatorKind.Equals,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.PipePipeToken,
|
||||||
|
BoundBinaryOperatorKind.PipePipe,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.AmpersandAmpersandToken,
|
||||||
|
BoundBinaryOperatorKind.AmpersandAmpersand,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.PipeToken,
|
||||||
|
BoundBinaryOperatorKind.Pipe,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.AmpersandToken,
|
||||||
|
BoundBinaryOperatorKind.Ampersand,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.LessToken,
|
||||||
|
BoundBinaryOperatorKind.Less,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.LessOrEqualsToken,
|
||||||
|
BoundBinaryOperatorKind.LessOrEquals,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.GreaterToken,
|
||||||
|
BoundBinaryOperatorKind.Greater,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.GreaterOrEqualsToken,
|
||||||
|
BoundBinaryOperatorKind.GreaterOrEquals,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.EqualsEqualsToken,
|
||||||
|
BoundBinaryOperatorKind.EqualsEquals,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.TildeEqualsToken,
|
||||||
|
BoundBinaryOperatorKind.TildeEquals,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.ColonToken,
|
||||||
|
BoundBinaryOperatorKind.Colon,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.PlusToken,
|
||||||
|
BoundBinaryOperatorKind.Plus,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.MinusToken,
|
||||||
|
BoundBinaryOperatorKind.Minus,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.StarToken,
|
||||||
|
BoundBinaryOperatorKind.Star,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.DotStarToken,
|
||||||
|
BoundBinaryOperatorKind.DotStar,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.SlashToken,
|
||||||
|
BoundBinaryOperatorKind.Slash,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.DotSlashToken,
|
||||||
|
BoundBinaryOperatorKind.DotSlash,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.BackslashToken,
|
||||||
|
BoundBinaryOperatorKind.Backslash,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.DotBackslashToken,
|
||||||
|
BoundBinaryOperatorKind.DotBackslash,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.TildeToken,
|
||||||
|
BoundBinaryOperatorKind.Tilde,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.CaretToken,
|
||||||
|
BoundBinaryOperatorKind.Caret,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
new BoundBinaryOperator(
|
||||||
|
TokenKind.DotCaretToken,
|
||||||
|
BoundBinaryOperatorKind.DotCaret,
|
||||||
|
TypeSymbol.MObject),
|
||||||
|
};
|
||||||
|
|
||||||
|
public BoundBinaryOperator(
|
||||||
|
TokenKind syntaxKind,
|
||||||
|
BoundBinaryOperatorKind kind,
|
||||||
|
TypeSymbol type)
|
||||||
{
|
{
|
||||||
SyntaxKind = syntaxKind;
|
SyntaxKind = syntaxKind;
|
||||||
Kind = kind;
|
Kind = kind;
|
||||||
|
Left = type;
|
||||||
|
Right = type;
|
||||||
|
Result = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundBinaryOperator(
|
||||||
|
TokenKind syntaxKind,
|
||||||
|
BoundBinaryOperatorKind kind,
|
||||||
|
TypeSymbol operand,
|
||||||
|
TypeSymbol result)
|
||||||
|
{
|
||||||
|
SyntaxKind = syntaxKind;
|
||||||
|
Kind = kind;
|
||||||
|
Left = operand;
|
||||||
|
Right = operand;
|
||||||
|
Result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundBinaryOperator(
|
||||||
|
TokenKind syntaxKind,
|
||||||
|
BoundBinaryOperatorKind kind,
|
||||||
|
TypeSymbol left,
|
||||||
|
TypeSymbol right,
|
||||||
|
TypeSymbol result)
|
||||||
|
{
|
||||||
|
SyntaxKind = syntaxKind;
|
||||||
|
Kind = kind;
|
||||||
|
Left = left;
|
||||||
|
Right = right;
|
||||||
|
Result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenKind SyntaxKind { get; }
|
public TokenKind SyntaxKind { get; }
|
||||||
public BoundBinaryOperatorKind Kind { get; }
|
public BoundBinaryOperatorKind Kind { get; }
|
||||||
|
public TypeSymbol Left { get; }
|
||||||
|
public TypeSymbol Right { get; }
|
||||||
|
public TypeSymbol Result { get; }
|
||||||
|
|
||||||
internal static BoundBinaryOperator? GetOperator(TokenKind kind)
|
internal static BoundBinaryOperator? GetOperator(TokenKind kind, TypeSymbol left, TypeSymbol right)
|
||||||
{
|
{
|
||||||
return _operators.FirstOrDefault(op => op.SyntaxKind == kind);
|
return _specificOperators.FirstOrDefault(op => op.SyntaxKind == kind && op.Left == left && op.Right == right)
|
||||||
|
?? _defaultOperators.FirstOrDefault(op => op.SyntaxKind == kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,11 @@ namespace Parser.Binding
|
|||||||
return new BoundBlockStatement(syntax, statements);
|
return new BoundBlockStatement(syntax, statements);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BoundConversionExpression Conversion(SyntaxNode syntax, TypeSymbol targetType, BoundExpression expression)
|
||||||
|
{
|
||||||
|
return new BoundConversionExpression(syntax, targetType, expression);
|
||||||
|
}
|
||||||
|
|
||||||
public static BoundExpressionStatement ExpressionStatement(
|
public static BoundExpressionStatement ExpressionStatement(
|
||||||
SyntaxNode syntax,
|
SyntaxNode syntax,
|
||||||
BoundExpression expression,
|
BoundExpression expression,
|
||||||
@ -43,6 +48,15 @@ namespace Parser.Binding
|
|||||||
return new BoundIfStatement(syntax, condition, body, elseifClauses, elseClause);
|
return new BoundIfStatement(syntax, condition, body, elseifClauses, elseClause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BoundForStatement ForStatement(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
BoundIdentifierNameExpression loopVariable,
|
||||||
|
BoundExpression loopExpression,
|
||||||
|
BoundStatement body)
|
||||||
|
{
|
||||||
|
return new BoundForStatement(syntax, loopVariable, loopExpression, body);
|
||||||
|
}
|
||||||
|
|
||||||
public static BoundLabelStatement LabelStatement(
|
public static BoundLabelStatement LabelStatement(
|
||||||
SyntaxNode syntax,
|
SyntaxNode syntax,
|
||||||
BoundLabel label)
|
BoundLabel label)
|
||||||
@ -61,10 +75,9 @@ namespace Parser.Binding
|
|||||||
public static BoundBinaryOperationExpression BinaryOperation(
|
public static BoundBinaryOperationExpression BinaryOperation(
|
||||||
SyntaxNode syntax,
|
SyntaxNode syntax,
|
||||||
BoundExpression left,
|
BoundExpression left,
|
||||||
TokenKind kind,
|
BoundBinaryOperator op,
|
||||||
BoundExpression right)
|
BoundExpression right)
|
||||||
{
|
{
|
||||||
var op = BindBinaryOperator(kind);
|
|
||||||
return new BoundBinaryOperationExpression(syntax, left, op, right);
|
return new BoundBinaryOperationExpression(syntax, left, op, right);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,11 +140,18 @@ namespace Parser.Binding
|
|||||||
return new BoundIdentifierNameExpression(syntax, name);
|
return new BoundIdentifierNameExpression(syntax, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BoundNumberLiteralExpression NumberLiteral(
|
public static BoundNumberDoubleLiteralExpression NumberDoubleLiteral(
|
||||||
SyntaxNode syntax,
|
SyntaxNode syntax,
|
||||||
double value)
|
double value)
|
||||||
{
|
{
|
||||||
return new BoundNumberLiteralExpression(syntax, value);
|
return new BoundNumberDoubleLiteralExpression(syntax, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BoundNumberIntLiteralExpression NumberIntLiteral(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
return new BoundNumberIntLiteralExpression(syntax, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BoundStringLiteralExpression StringLiteral(
|
public static BoundStringLiteralExpression StringLiteral(
|
||||||
@ -149,25 +169,38 @@ namespace Parser.Binding
|
|||||||
return new BoundElseifClause(syntax, condition, body);
|
return new BoundElseifClause(syntax, condition, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static BoundTypedVariableDeclaration TypedVariableDeclaration(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
TypedVariableSymbol variable,
|
||||||
|
BoundExpression initializer)
|
||||||
|
{
|
||||||
|
return new BoundTypedVariableDeclaration(syntax, variable, initializer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BoundTypedVariableExpression TypedVariableExpression(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
TypedVariableSymbol variable)
|
||||||
|
{
|
||||||
|
return new BoundTypedVariableExpression(syntax, variable);
|
||||||
|
}
|
||||||
|
|
||||||
public static BoundUnaryOperationExpression UnaryOperation(
|
public static BoundUnaryOperationExpression UnaryOperation(
|
||||||
SyntaxNode syntax,
|
SyntaxNode syntax,
|
||||||
TokenKind kind,
|
BoundUnaryOperator op,
|
||||||
BoundExpression operand)
|
BoundExpression operand)
|
||||||
{
|
{
|
||||||
var op = BindUnaryOperator(kind);
|
|
||||||
return new BoundUnaryOperationExpression(syntax, op, operand);
|
return new BoundUnaryOperationExpression(syntax, op, operand);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static BoundUnaryOperator BindUnaryOperator(TokenKind kind)
|
public static BoundExpression TypedFunctionCall(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
TypedFunctionSymbol function,
|
||||||
|
ImmutableArray<BoundExpression> arguments)
|
||||||
{
|
{
|
||||||
return BoundUnaryOperator.GetOperator(kind)
|
return new BoundTypedFunctionCallExpression(
|
||||||
?? throw new Exception($"Unexpected unary operator kind {kind}.");
|
syntax,
|
||||||
}
|
function,
|
||||||
|
arguments);
|
||||||
private static BoundBinaryOperator BindBinaryOperator(TokenKind kind)
|
|
||||||
{
|
|
||||||
return BoundBinaryOperator.GetOperator(kind)
|
|
||||||
?? throw new Exception($"Unexpected binary operator kind {kind}.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
LabelStatement,
|
LabelStatement,
|
||||||
SwitchStatement,
|
SwitchStatement,
|
||||||
TryCatchStatement,
|
TryCatchStatement,
|
||||||
|
TypedVariableDeclaration,
|
||||||
WhileStatement,
|
WhileStatement,
|
||||||
|
|
||||||
// Expressions
|
// Expressions
|
||||||
@ -33,8 +34,10 @@
|
|||||||
ClassInvokationExpression,
|
ClassInvokationExpression,
|
||||||
CommandExpression,
|
CommandExpression,
|
||||||
CompoundNameExpression,
|
CompoundNameExpression,
|
||||||
|
ConversionExpression,
|
||||||
DoubleQuotedStringLiteralExpression,
|
DoubleQuotedStringLiteralExpression,
|
||||||
EmptyExpression,
|
EmptyExpression,
|
||||||
|
ErrorExpression,
|
||||||
FunctionCallExpression,
|
FunctionCallExpression,
|
||||||
IdentifierNameExpression,
|
IdentifierNameExpression,
|
||||||
IndirectMemberAccessExpression,
|
IndirectMemberAccessExpression,
|
||||||
@ -44,11 +47,13 @@
|
|||||||
NumberLiteralExpression,
|
NumberLiteralExpression,
|
||||||
ParenthesizedExpression,
|
ParenthesizedExpression,
|
||||||
StringLiteralExpression,
|
StringLiteralExpression,
|
||||||
|
TypedFunctionCallExpression,
|
||||||
|
TypedVariableExpression,
|
||||||
UnaryOperationExpression,
|
UnaryOperationExpression,
|
||||||
UnquotedStringLiteralExpression,
|
UnquotedStringLiteralExpression,
|
||||||
|
|
||||||
// Parts
|
// Parts
|
||||||
ElseIfClause,
|
ElseIfClause,
|
||||||
ElseClause
|
ElseClause,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -134,11 +134,24 @@ namespace Parser.Binding
|
|||||||
|
|
||||||
public class BoundForStatement : BoundStatement
|
public class BoundForStatement : BoundStatement
|
||||||
{
|
{
|
||||||
public BoundForStatement(SyntaxNode syntax)
|
public BoundForStatement(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
BoundIdentifierNameExpression loopVariable,
|
||||||
|
BoundExpression loopedExpression,
|
||||||
|
BoundStatement body)
|
||||||
: base(syntax)
|
: base(syntax)
|
||||||
{
|
{
|
||||||
|
LoopVariable = loopVariable;
|
||||||
|
LoopedExpression = loopedExpression;
|
||||||
|
Body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BoundIdentifierNameExpression LoopVariable { get; }
|
||||||
|
|
||||||
|
public BoundExpression LoopedExpression { get; }
|
||||||
|
|
||||||
|
public BoundStatement Body { get; }
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.ForStatement;
|
public override BoundNodeKind Kind => BoundNodeKind.ForStatement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -257,6 +270,8 @@ namespace Parser.Binding
|
|||||||
: base(syntax)
|
: base(syntax)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract TypeSymbol Type { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundArrayLiteralExpression : BoundExpression
|
public class BoundArrayLiteralExpression : BoundExpression
|
||||||
@ -267,6 +282,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.ArrayLiteralExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.ArrayLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundAssignmentExpression : BoundExpression
|
public class BoundAssignmentExpression : BoundExpression
|
||||||
@ -282,6 +299,8 @@ namespace Parser.Binding
|
|||||||
public BoundExpression Right { get; }
|
public BoundExpression Right { get; }
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.AssignmentExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.AssignmentExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => Right.Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundBinaryOperationExpression : BoundExpression
|
public class BoundBinaryOperationExpression : BoundExpression
|
||||||
@ -299,6 +318,8 @@ namespace Parser.Binding
|
|||||||
public BoundExpression Right { get; }
|
public BoundExpression Right { get; }
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.BinaryOperationExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.BinaryOperationExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => Op.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundCellArrayElementAccessExpression : BoundExpression
|
public class BoundCellArrayElementAccessExpression : BoundExpression
|
||||||
@ -309,6 +330,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.CellArrayElementAccessExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.CellArrayElementAccessExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundCellArrayLiteralExpression : BoundExpression
|
public class BoundCellArrayLiteralExpression : BoundExpression
|
||||||
@ -319,6 +342,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.CellArrayLiteralExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.CellArrayLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundClassInvokationExpression : BoundExpression
|
public class BoundClassInvokationExpression : BoundExpression
|
||||||
@ -329,6 +354,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.ClassInvokationExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.ClassInvokationExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundCommandExpression : BoundExpression
|
public class BoundCommandExpression : BoundExpression
|
||||||
@ -339,6 +366,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.CommandExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.CommandExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundCompoundNameExpression : BoundExpression
|
public class BoundCompoundNameExpression : BoundExpression
|
||||||
@ -349,6 +378,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.CompoundNameExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.CompoundNameExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundDoubleQuotedStringLiteralExpression : BoundExpression
|
public class BoundDoubleQuotedStringLiteralExpression : BoundExpression
|
||||||
@ -359,6 +390,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.DoubleQuotedStringLiteralExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.DoubleQuotedStringLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundEmptyExpression : BoundExpression
|
public class BoundEmptyExpression : BoundExpression
|
||||||
@ -369,6 +402,20 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.EmptyExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.EmptyExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TypeSymbol.Null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundErrorExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public BoundErrorExpression(SyntaxNode syntax)
|
||||||
|
: base(syntax)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override BoundNodeKind Kind => BoundNodeKind.ErrorExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TypeSymbol.Error;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundFunctionCallExpression : BoundExpression
|
public class BoundFunctionCallExpression : BoundExpression
|
||||||
@ -383,6 +430,27 @@ namespace Parser.Binding
|
|||||||
public BoundExpression Name { get; }
|
public BoundExpression Name { get; }
|
||||||
public ImmutableArray<BoundExpression> Arguments { get; }
|
public ImmutableArray<BoundExpression> Arguments { get; }
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.FunctionCallExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.FunctionCallExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundTypedFunctionCallExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public BoundTypedFunctionCallExpression(
|
||||||
|
SyntaxNode syntax,
|
||||||
|
TypedFunctionSymbol function,
|
||||||
|
ImmutableArray<BoundExpression> arguments)
|
||||||
|
: base(syntax)
|
||||||
|
{
|
||||||
|
Function = function;
|
||||||
|
Arguments = arguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypedFunctionSymbol Function { get; }
|
||||||
|
public ImmutableArray<BoundExpression> Arguments { get; }
|
||||||
|
public override BoundNodeKind Kind => BoundNodeKind.TypedFunctionCallExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => Function.ReturnType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundIdentifierNameExpression : BoundExpression
|
public class BoundIdentifierNameExpression : BoundExpression
|
||||||
@ -395,6 +463,8 @@ namespace Parser.Binding
|
|||||||
|
|
||||||
public string Name { get; }
|
public string Name { get; }
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.IdentifierNameExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.IdentifierNameExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TypeSymbol.MObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundIndirectMemberAccessExpression : BoundExpression
|
public class BoundIndirectMemberAccessExpression : BoundExpression
|
||||||
@ -405,6 +475,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.IndirectMemberAccessExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.IndirectMemberAccessExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundLambdaExpression : BoundExpression
|
public class BoundLambdaExpression : BoundExpression
|
||||||
@ -415,6 +487,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.LambdaExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.LambdaExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundMemberAccessExpression : BoundExpression
|
public class BoundMemberAccessExpression : BoundExpression
|
||||||
@ -425,6 +499,8 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.MemberAccessExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.MemberAccessExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundNamedFunctionHandleExpression : BoundExpression
|
public class BoundNamedFunctionHandleExpression : BoundExpression
|
||||||
@ -435,11 +511,13 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.NamedFunctionHandleExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.NamedFunctionHandleExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundNumberLiteralExpression : BoundExpression
|
public class BoundNumberDoubleLiteralExpression : BoundExpression
|
||||||
{
|
{
|
||||||
public BoundNumberLiteralExpression(SyntaxNode syntax, double value)
|
public BoundNumberDoubleLiteralExpression(SyntaxNode syntax, double value)
|
||||||
: base(syntax)
|
: base(syntax)
|
||||||
{
|
{
|
||||||
Value = value;
|
Value = value;
|
||||||
@ -447,6 +525,22 @@ namespace Parser.Binding
|
|||||||
|
|
||||||
public double Value { get; }
|
public double Value { get; }
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.NumberLiteralExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.NumberLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TypeSymbol.Double;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundNumberIntLiteralExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public BoundNumberIntLiteralExpression(SyntaxNode syntax, int value)
|
||||||
|
: base(syntax)
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Value { get; }
|
||||||
|
public override BoundNodeKind Kind => BoundNodeKind.NumberLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TypeSymbol.Int;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundStringLiteralExpression : BoundExpression
|
public class BoundStringLiteralExpression : BoundExpression
|
||||||
@ -459,6 +553,39 @@ namespace Parser.Binding
|
|||||||
|
|
||||||
public string Value { get; }
|
public string Value { get; }
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.StringLiteralExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.StringLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TypeSymbol.String;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundTypedVariableDeclaration : BoundStatement
|
||||||
|
{
|
||||||
|
public BoundTypedVariableDeclaration(SyntaxNode syntax, TypedVariableSymbol variable, BoundExpression initializer)
|
||||||
|
: base(syntax)
|
||||||
|
{
|
||||||
|
Variable = variable;
|
||||||
|
Initializer = initializer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypedVariableSymbol Variable { get; }
|
||||||
|
|
||||||
|
public BoundExpression Initializer { get; }
|
||||||
|
|
||||||
|
public override BoundNodeKind Kind => BoundNodeKind.TypedVariableDeclaration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundTypedVariableExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public BoundTypedVariableExpression(SyntaxNode syntax, TypedVariableSymbol variable)
|
||||||
|
: base(syntax)
|
||||||
|
{
|
||||||
|
Variable = variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypedVariableSymbol Variable { get; }
|
||||||
|
|
||||||
|
public override BoundNodeKind Kind => BoundNodeKind.TypedVariableExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => Variable.Type;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundUnaryOperationExpression : BoundExpression
|
public class BoundUnaryOperationExpression : BoundExpression
|
||||||
@ -474,6 +601,8 @@ namespace Parser.Binding
|
|||||||
|
|
||||||
public BoundUnaryOperator Op { get; }
|
public BoundUnaryOperator Op { get; }
|
||||||
public BoundExpression Operand { get; }
|
public BoundExpression Operand { get; }
|
||||||
|
|
||||||
|
public override TypeSymbol Type => Op.Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundUnquotedStringLiteralExpression : BoundExpression
|
public class BoundUnquotedStringLiteralExpression : BoundExpression
|
||||||
@ -484,6 +613,26 @@ namespace Parser.Binding
|
|||||||
}
|
}
|
||||||
|
|
||||||
public override BoundNodeKind Kind => BoundNodeKind.UnquotedStringLiteralExpression;
|
public override BoundNodeKind Kind => BoundNodeKind.UnquotedStringLiteralExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class BoundConversionExpression : BoundExpression
|
||||||
|
{
|
||||||
|
public BoundConversionExpression(SyntaxNode syntax, TypeSymbol targetType, BoundExpression expression)
|
||||||
|
: base(syntax)
|
||||||
|
{
|
||||||
|
TargetType = targetType;
|
||||||
|
Expression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TypeSymbol TargetType { get; }
|
||||||
|
|
||||||
|
public BoundExpression Expression { get; }
|
||||||
|
|
||||||
|
public override BoundNodeKind Kind => BoundNodeKind.ConversionExpression;
|
||||||
|
|
||||||
|
public override TypeSymbol Type => TargetType;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundElseifClause : BoundNode
|
public class BoundElseifClause : BoundNode
|
||||||
|
@ -38,6 +38,8 @@ namespace Parser.Binding
|
|||||||
RewriteSwitchStatement((BoundSwitchStatement)node),
|
RewriteSwitchStatement((BoundSwitchStatement)node),
|
||||||
BoundNodeKind.TryCatchStatement =>
|
BoundNodeKind.TryCatchStatement =>
|
||||||
RewriteTryCatchStatement((BoundTryCatchStatement)node),
|
RewriteTryCatchStatement((BoundTryCatchStatement)node),
|
||||||
|
BoundNodeKind.TypedVariableDeclaration =>
|
||||||
|
RewriteTypedVariableDeclaration((BoundTypedVariableDeclaration)node),
|
||||||
BoundNodeKind.WhileStatement =>
|
BoundNodeKind.WhileStatement =>
|
||||||
RewriteWhileStatement((BoundWhileStatement)node),
|
RewriteWhileStatement((BoundWhileStatement)node),
|
||||||
_ =>
|
_ =>
|
||||||
@ -45,6 +47,11 @@ namespace Parser.Binding
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual BoundStatement RewriteTypedVariableDeclaration(BoundTypedVariableDeclaration node)
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual BoundStatement RewriteGotoStatement(BoundGotoStatement node)
|
public virtual BoundStatement RewriteGotoStatement(BoundGotoStatement node)
|
||||||
{
|
{
|
||||||
return node;
|
return node;
|
||||||
@ -136,7 +143,7 @@ namespace Parser.Binding
|
|||||||
|
|
||||||
public virtual BoundStatement RewriteForStatement(BoundForStatement node)
|
public virtual BoundStatement RewriteForStatement(BoundForStatement node)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual BoundStatement RewriteExpressionStatement(BoundExpressionStatement node)
|
public virtual BoundStatement RewriteExpressionStatement(BoundExpressionStatement node)
|
||||||
@ -220,6 +227,8 @@ namespace Parser.Binding
|
|||||||
RewriteCommandExpression((BoundCommandExpression)node),
|
RewriteCommandExpression((BoundCommandExpression)node),
|
||||||
BoundNodeKind.CompoundNameExpression =>
|
BoundNodeKind.CompoundNameExpression =>
|
||||||
RewriteCompoundNameExpression((BoundCompoundNameExpression)node),
|
RewriteCompoundNameExpression((BoundCompoundNameExpression)node),
|
||||||
|
BoundNodeKind.ConversionExpression =>
|
||||||
|
RewriteConversionExpression((BoundConversionExpression)node),
|
||||||
BoundNodeKind.DoubleQuotedStringLiteralExpression =>
|
BoundNodeKind.DoubleQuotedStringLiteralExpression =>
|
||||||
RewriteDoubleQuotedStringLiteralExpression((BoundDoubleQuotedStringLiteralExpression)node),
|
RewriteDoubleQuotedStringLiteralExpression((BoundDoubleQuotedStringLiteralExpression)node),
|
||||||
BoundNodeKind.EmptyExpression =>
|
BoundNodeKind.EmptyExpression =>
|
||||||
@ -237,9 +246,11 @@ namespace Parser.Binding
|
|||||||
BoundNodeKind.NamedFunctionHandleExpression =>
|
BoundNodeKind.NamedFunctionHandleExpression =>
|
||||||
RewriteNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node),
|
RewriteNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node),
|
||||||
BoundNodeKind.NumberLiteralExpression =>
|
BoundNodeKind.NumberLiteralExpression =>
|
||||||
RewriteNumberLiteralExpression((BoundNumberLiteralExpression)node),
|
RewriteNumberLiteralExpression((BoundNumberDoubleLiteralExpression)node),
|
||||||
BoundNodeKind.StringLiteralExpression =>
|
BoundNodeKind.StringLiteralExpression =>
|
||||||
RewriteStringLiteralExpression((BoundStringLiteralExpression)node),
|
RewriteStringLiteralExpression((BoundStringLiteralExpression)node),
|
||||||
|
BoundNodeKind.TypedVariableExpression =>
|
||||||
|
RewriteTypedVariableExpression((BoundTypedVariableExpression)node),
|
||||||
BoundNodeKind.UnaryOperationExpression =>
|
BoundNodeKind.UnaryOperationExpression =>
|
||||||
RewriteUnaryOperationExpression((BoundUnaryOperationExpression)node),
|
RewriteUnaryOperationExpression((BoundUnaryOperationExpression)node),
|
||||||
BoundNodeKind.UnquotedStringLiteralExpression =>
|
BoundNodeKind.UnquotedStringLiteralExpression =>
|
||||||
@ -249,6 +260,17 @@ namespace Parser.Binding
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public virtual BoundExpression RewriteConversionExpression(BoundConversionExpression node)
|
||||||
|
{
|
||||||
|
var operand = RewriteExpression(node.Expression);
|
||||||
|
return Conversion(node.Syntax, node.TargetType, operand);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual BoundExpression RewriteTypedVariableExpression(BoundTypedVariableExpression node)
|
||||||
|
{
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
public virtual BoundExpression RewriteUnquotedStringLiteralExpression(BoundUnquotedStringLiteralExpression node)
|
public virtual BoundExpression RewriteUnquotedStringLiteralExpression(BoundUnquotedStringLiteralExpression node)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
@ -265,7 +287,7 @@ namespace Parser.Binding
|
|||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual BoundExpression RewriteNumberLiteralExpression(BoundNumberLiteralExpression node)
|
public virtual BoundExpression RewriteNumberLiteralExpression(BoundNumberDoubleLiteralExpression node)
|
||||||
{
|
{
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -1,26 +1,42 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Parser.Binding
|
namespace Parser.Binding
|
||||||
{
|
{
|
||||||
public class BoundUnaryOperator
|
public class BoundUnaryOperator
|
||||||
{
|
{
|
||||||
private static BoundUnaryOperator[] _operators =
|
private static BoundUnaryOperator[] _specificOperators = Array.Empty<BoundUnaryOperator>();
|
||||||
|
|
||||||
|
private static BoundUnaryOperator[] _defaultOperators =
|
||||||
{
|
{
|
||||||
new BoundUnaryOperator(TokenKind.MinusToken, BoundUnaryOperatorKind.Minus),
|
new BoundUnaryOperator(TokenKind.MinusToken, BoundUnaryOperatorKind.Minus, TypeSymbol.MObject),
|
||||||
};
|
};
|
||||||
|
|
||||||
public BoundUnaryOperator(TokenKind syntaxKind, BoundUnaryOperatorKind kind)
|
public BoundUnaryOperator(TokenKind syntaxKind, BoundUnaryOperatorKind kind, TypeSymbol type)
|
||||||
{
|
{
|
||||||
SyntaxKind = syntaxKind;
|
SyntaxKind = syntaxKind;
|
||||||
Kind = kind;
|
Kind = kind;
|
||||||
|
Operand = type;
|
||||||
|
Result = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BoundUnaryOperator(TokenKind syntaxKind, BoundUnaryOperatorKind kind, TypeSymbol operand, TypeSymbol result)
|
||||||
|
{
|
||||||
|
SyntaxKind = syntaxKind;
|
||||||
|
Kind = kind;
|
||||||
|
Operand = operand;
|
||||||
|
Result = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TokenKind SyntaxKind { get; }
|
public TokenKind SyntaxKind { get; }
|
||||||
public BoundUnaryOperatorKind Kind { get; }
|
public BoundUnaryOperatorKind Kind { get; }
|
||||||
|
public TypeSymbol Operand { get; }
|
||||||
|
public TypeSymbol Result { get; }
|
||||||
|
|
||||||
internal static BoundUnaryOperator? GetOperator(TokenKind kind)
|
internal static BoundUnaryOperator? GetOperator(TokenKind kind, TypeSymbol operand)
|
||||||
{
|
{
|
||||||
return _operators.FirstOrDefault(op => op.SyntaxKind == kind);
|
return _specificOperators.FirstOrDefault(op => op.SyntaxKind == kind && op.Operand == operand)
|
||||||
|
?? _defaultOperators.FirstOrDefault(op => op.SyntaxKind == kind);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
34
Parser/Binding/Conversion.cs
Normal file
34
Parser/Binding/Conversion.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
namespace Parser.Binding
|
||||||
|
{
|
||||||
|
internal class Conversion
|
||||||
|
{
|
||||||
|
public static Conversion None = new Conversion(exists: false, isIdentity: false);
|
||||||
|
public static Conversion Identity = new Conversion(exists: true, isIdentity: true);
|
||||||
|
public static Conversion Implicit = new Conversion(exists: true, isIdentity: false);
|
||||||
|
|
||||||
|
private Conversion(bool exists, bool isIdentity)
|
||||||
|
{
|
||||||
|
Exists = exists;
|
||||||
|
IsIdentity = isIdentity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Exists { get; }
|
||||||
|
|
||||||
|
public bool IsIdentity { get; }
|
||||||
|
|
||||||
|
public static Conversion Classify(TypeSymbol from, TypeSymbol to)
|
||||||
|
{
|
||||||
|
if (from == to)
|
||||||
|
{
|
||||||
|
return Identity;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (to == TypeSymbol.MObject)
|
||||||
|
{
|
||||||
|
return Implicit;
|
||||||
|
}
|
||||||
|
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
26
Parser/Binding/TypeSymbol.cs
Normal file
26
Parser/Binding/TypeSymbol.cs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
namespace Parser.Binding
|
||||||
|
{
|
||||||
|
public class TypeSymbol
|
||||||
|
{
|
||||||
|
public static readonly TypeSymbol Error = new TypeSymbol("error");
|
||||||
|
public static readonly TypeSymbol Null = new TypeSymbol("null");
|
||||||
|
public static readonly TypeSymbol Boolean = new TypeSymbol("bool");
|
||||||
|
public static readonly TypeSymbol Double = new TypeSymbol("double");
|
||||||
|
public static readonly TypeSymbol Int = new TypeSymbol("int");
|
||||||
|
public static readonly TypeSymbol String = new TypeSymbol("string");
|
||||||
|
public static readonly TypeSymbol MObject = new TypeSymbol("mobject");
|
||||||
|
public static readonly TypeSymbol Void = new TypeSymbol("void");
|
||||||
|
|
||||||
|
private TypeSymbol(string name)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return Name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
Parser/Binding/TypedFunctionSymbol.cs
Normal file
23
Parser/Binding/TypedFunctionSymbol.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections.Immutable;
|
||||||
|
|
||||||
|
namespace Parser.Binding
|
||||||
|
{
|
||||||
|
public class TypedFunctionSymbol
|
||||||
|
{
|
||||||
|
public TypedFunctionSymbol(
|
||||||
|
string name,
|
||||||
|
ImmutableArray<TypedParameterSymbol> parameters,
|
||||||
|
TypeSymbol returnType)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Parameters = parameters;
|
||||||
|
ReturnType = returnType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public ImmutableArray<TypedParameterSymbol> Parameters { get; }
|
||||||
|
|
||||||
|
public TypeSymbol ReturnType { get; }
|
||||||
|
}
|
||||||
|
}
|
14
Parser/Binding/TypedParameterSymbol.cs
Normal file
14
Parser/Binding/TypedParameterSymbol.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
namespace Parser.Binding
|
||||||
|
{
|
||||||
|
public class TypedParameterSymbol
|
||||||
|
{
|
||||||
|
public TypedParameterSymbol(string name, TypeSymbol type)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
public TypeSymbol Type { get; }
|
||||||
|
}
|
||||||
|
}
|
15
Parser/Binding/TypedVariableSymbol.cs
Normal file
15
Parser/Binding/TypedVariableSymbol.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
namespace Parser.Binding
|
||||||
|
{
|
||||||
|
public class TypedVariableSymbol
|
||||||
|
{
|
||||||
|
public TypedVariableSymbol(string name, TypeSymbol type)
|
||||||
|
{
|
||||||
|
Name = name;
|
||||||
|
Type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Name { get; }
|
||||||
|
|
||||||
|
public TypeSymbol Type { get; }
|
||||||
|
}
|
||||||
|
}
|
@ -4,20 +4,34 @@ using Mono.Cecil.Rocks;
|
|||||||
using Parser.Binding;
|
using Parser.Binding;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Immutable;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Parser.Emitting
|
namespace Parser.Emitting
|
||||||
{
|
{
|
||||||
|
public static class BuiltInFunctions
|
||||||
|
{
|
||||||
|
public static readonly TypedFunctionSymbol Disp = new TypedFunctionSymbol(
|
||||||
|
"disp",
|
||||||
|
ImmutableArray.Create(
|
||||||
|
new TypedParameterSymbol("text", TypeSymbol.MObject)),
|
||||||
|
TypeSymbol.Void);
|
||||||
|
}
|
||||||
|
|
||||||
public class Emitter
|
public class Emitter
|
||||||
{
|
{
|
||||||
private Dictionary<string, TypeReference> _knownTypes = new Dictionary<string, TypeReference>();
|
private Dictionary<string, TypeReference> _knownTypes = new Dictionary<string, TypeReference>();
|
||||||
|
private Dictionary<TypeSymbol, TypeReference> _resolvedTypes = new Dictionary<TypeSymbol, TypeReference>();
|
||||||
private Dictionary<string, MethodInterfaceDescription> _functions = new Dictionary<string, MethodInterfaceDescription>();
|
private Dictionary<string, MethodInterfaceDescription> _functions = new Dictionary<string, MethodInterfaceDescription>();
|
||||||
private MethodReference? _consoleWriteLineReference;
|
private MethodReference? _consoleWriteLineReference;
|
||||||
private MethodReference? _dispReference;
|
private MethodReference? _dispReference;
|
||||||
|
private MethodReference? _lenReference;
|
||||||
|
private MethodReference? _arraySliceReference;
|
||||||
private MethodReference? _mObjectToBool;
|
private MethodReference? _mObjectToBool;
|
||||||
private MethodReference? _stringToMObject;
|
private MethodReference? _stringToMObject;
|
||||||
private MethodReference? _doubleToMObject;
|
private MethodReference? _doubleToMObject;
|
||||||
|
private MethodReference? _intToMObject;
|
||||||
private MethodReference? _getItemFromDictionary;
|
private MethodReference? _getItemFromDictionary;
|
||||||
private MethodReference? _putItemIntoDictionary;
|
private MethodReference? _putItemIntoDictionary;
|
||||||
private TypeReference? _mObjectType;
|
private TypeReference? _mObjectType;
|
||||||
@ -30,6 +44,8 @@ namespace Parser.Emitting
|
|||||||
private Dictionary<BoundUnaryOperatorKind, MethodReference> _unaryOperations = new Dictionary<BoundUnaryOperatorKind, MethodReference>();
|
private Dictionary<BoundUnaryOperatorKind, MethodReference> _unaryOperations = new Dictionary<BoundUnaryOperatorKind, MethodReference>();
|
||||||
private Dictionary<BoundLabel, int> _labels = new Dictionary<BoundLabel, int>();
|
private Dictionary<BoundLabel, int> _labels = new Dictionary<BoundLabel, int>();
|
||||||
private Dictionary<int, BoundLabel> _forwardLabelsToFix = new Dictionary<int, BoundLabel>();
|
private Dictionary<int, BoundLabel> _forwardLabelsToFix = new Dictionary<int, BoundLabel>();
|
||||||
|
private Dictionary<TypedVariableSymbol, VariableDefinition> _typedLocals = new Dictionary<TypedVariableSymbol, VariableDefinition>();
|
||||||
|
private Dictionary<TypedFunctionSymbol, MethodReference> _builtInFunctions = new Dictionary<TypedFunctionSymbol, MethodReference>();
|
||||||
|
|
||||||
private static TypeReference ResolveAndImportType(
|
private static TypeReference ResolveAndImportType(
|
||||||
string typeName,
|
string typeName,
|
||||||
@ -132,6 +148,7 @@ namespace Parser.Emitting
|
|||||||
kind: ModuleKind.Console);
|
kind: ModuleKind.Console);
|
||||||
var builtInTypes = new[]
|
var builtInTypes = new[]
|
||||||
{
|
{
|
||||||
|
"System.Int32",
|
||||||
"System.Object",
|
"System.Object",
|
||||||
"System.Void",
|
"System.Void",
|
||||||
"System.String",
|
"System.String",
|
||||||
@ -139,6 +156,12 @@ namespace Parser.Emitting
|
|||||||
"Parser.Objects.MObject"
|
"Parser.Objects.MObject"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
var typeSymbolToKnownType = new Dictionary<TypeSymbol, string>
|
||||||
|
{
|
||||||
|
[TypeSymbol.Int] = "System.Int32",
|
||||||
|
[TypeSymbol.MObject] = "Parser.Objects.MObject",
|
||||||
|
};
|
||||||
|
|
||||||
// Resolve built-in types and methods.
|
// Resolve built-in types and methods.
|
||||||
foreach (var typeName in builtInTypes)
|
foreach (var typeName in builtInTypes)
|
||||||
{
|
{
|
||||||
@ -146,6 +169,11 @@ namespace Parser.Emitting
|
|||||||
_knownTypes.Add(typeName, typeReference);
|
_knownTypes.Add(typeName, typeReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (var (typeSymbol, knownTypeName) in typeSymbolToKnownType)
|
||||||
|
{
|
||||||
|
_resolvedTypes.Add(typeSymbol, _knownTypes[knownTypeName]);
|
||||||
|
}
|
||||||
|
|
||||||
var objectType = _knownTypes["System.Object"];
|
var objectType = _knownTypes["System.Object"];
|
||||||
var voidType = _knownTypes["System.Void"];
|
var voidType = _knownTypes["System.Void"];
|
||||||
var stringType = _knownTypes["System.String"];
|
var stringType = _knownTypes["System.String"];
|
||||||
@ -192,6 +220,20 @@ namespace Parser.Emitting
|
|||||||
assemblies: assemblies,
|
assemblies: assemblies,
|
||||||
assemblyDefinition: assemblyDefinition);
|
assemblyDefinition: assemblyDefinition);
|
||||||
|
|
||||||
|
_lenReference = ResolveAndImportMethod(
|
||||||
|
typeName: "Parser.MFunctions.MHelpers",
|
||||||
|
methodName: "Len",
|
||||||
|
parameterTypeNames: new[] { "Parser.Objects.MObject" },
|
||||||
|
assemblies: assemblies,
|
||||||
|
assemblyDefinition: assemblyDefinition);
|
||||||
|
|
||||||
|
_arraySliceReference = ResolveAndImportMethod(
|
||||||
|
typeName: "Parser.MFunctions.MOperations",
|
||||||
|
methodName: "ArraySlice",
|
||||||
|
parameterTypeNames: new[] { "Parser.Objects.MObject", "Parser.Objects.MObject" },
|
||||||
|
assemblies: assemblies,
|
||||||
|
assemblyDefinition: assemblyDefinition);
|
||||||
|
|
||||||
_mObjectToBool = ResolveAndImportMethod(
|
_mObjectToBool = ResolveAndImportMethod(
|
||||||
typeName: "Parser.MFunctions.MHelpers",
|
typeName: "Parser.MFunctions.MHelpers",
|
||||||
methodName: "ToBool",
|
methodName: "ToBool",
|
||||||
@ -213,8 +255,16 @@ namespace Parser.Emitting
|
|||||||
assemblies: assemblies,
|
assemblies: assemblies,
|
||||||
assemblyDefinition: assemblyDefinition);
|
assemblyDefinition: assemblyDefinition);
|
||||||
|
|
||||||
|
_intToMObject = ResolveAndImportMethod(
|
||||||
|
typeName: "Parser.Objects.MObject",
|
||||||
|
methodName: "CreateIntNumber",
|
||||||
|
parameterTypeNames: new[] { "System.Int32" },
|
||||||
|
assemblies: assemblies,
|
||||||
|
assemblyDefinition: assemblyDefinition);
|
||||||
|
|
||||||
var binaryOperationNames = new Dictionary<BoundBinaryOperatorKind, string>
|
var binaryOperationNames = new Dictionary<BoundBinaryOperatorKind, string>
|
||||||
{
|
{
|
||||||
|
[BoundBinaryOperatorKind.Colon] = "Colon",
|
||||||
[BoundBinaryOperatorKind.Plus] = "Plus",
|
[BoundBinaryOperatorKind.Plus] = "Plus",
|
||||||
[BoundBinaryOperatorKind.Minus] = "Minus",
|
[BoundBinaryOperatorKind.Minus] = "Minus",
|
||||||
[BoundBinaryOperatorKind.Star] = "Star",
|
[BoundBinaryOperatorKind.Star] = "Star",
|
||||||
@ -230,6 +280,10 @@ namespace Parser.Emitting
|
|||||||
[BoundUnaryOperatorKind.Minus] = "Minus",
|
[BoundUnaryOperatorKind.Minus] = "Minus",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_builtInFunctions.Add(
|
||||||
|
BuiltInFunctions.Disp,
|
||||||
|
_dispReference);
|
||||||
|
|
||||||
foreach (var (op, opName) in binaryOperationNames)
|
foreach (var (op, opName) in binaryOperationNames)
|
||||||
{
|
{
|
||||||
_binaryOperations[op] = ResolveAndImportMethod(
|
_binaryOperations[op] = ResolveAndImportMethod(
|
||||||
@ -306,10 +360,12 @@ namespace Parser.Emitting
|
|||||||
|
|
||||||
private void EmitFunction(LoweredFunction function, MethodDefinition methodDefinition)
|
private void EmitFunction(LoweredFunction function, MethodDefinition methodDefinition)
|
||||||
{
|
{
|
||||||
|
Console.WriteLine($"Emitting function '{function.Name}'.");
|
||||||
var ilProcessor = methodDefinition.Body.GetILProcessor();
|
var ilProcessor = methodDefinition.Body.GetILProcessor();
|
||||||
|
|
||||||
_labels.Clear();
|
_labels.Clear();
|
||||||
_forwardLabelsToFix.Clear();
|
_forwardLabelsToFix.Clear();
|
||||||
|
_typedLocals.Clear();
|
||||||
|
|
||||||
// Local #0 is the dictionary with actual local variables.
|
// Local #0 is the dictionary with actual local variables.
|
||||||
_currentLocals = new VariableDefinition(_stringMObjectDictionary);
|
_currentLocals = new VariableDefinition(_stringMObjectDictionary);
|
||||||
@ -356,13 +412,16 @@ namespace Parser.Emitting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ilProcessor.Emit(OpCodes.Ret);
|
||||||
|
|
||||||
foreach (var (index, target) in _forwardLabelsToFix)
|
foreach (var (index, target) in _forwardLabelsToFix)
|
||||||
{
|
{
|
||||||
var targetIndex = _labels[target];
|
var targetIndex = _labels[target];
|
||||||
ilProcessor.Body.Instructions[index].Operand = ilProcessor.Body.Instructions[targetIndex];
|
var left = ilProcessor.Body.Instructions[index];
|
||||||
|
var right = ilProcessor.Body.Instructions[targetIndex];
|
||||||
|
left.Operand = right;
|
||||||
}
|
}
|
||||||
|
|
||||||
ilProcessor.Emit(OpCodes.Ret);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitBlockStatement(BoundBlockStatement block, MethodDefinition methodDefinition)
|
private void EmitBlockStatement(BoundBlockStatement block, MethodDefinition methodDefinition)
|
||||||
@ -431,11 +490,25 @@ namespace Parser.Emitting
|
|||||||
case BoundNodeKind.ExpressionStatement:
|
case BoundNodeKind.ExpressionStatement:
|
||||||
EmitExpressionStatement((BoundExpressionStatement)node, ilProcessor);
|
EmitExpressionStatement((BoundExpressionStatement)node, ilProcessor);
|
||||||
break;
|
break;
|
||||||
|
case BoundNodeKind.TypedVariableDeclaration:
|
||||||
|
EmitTypedVariableDeclaration((BoundTypedVariableDeclaration)node, ilProcessor);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"Invalid statement kind '{node.Kind}'.");
|
throw new NotImplementedException($"Invalid statement kind '{node.Kind}'.");
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EmitTypedVariableDeclaration(BoundTypedVariableDeclaration node, ILProcessor ilProcessor)
|
||||||
|
{
|
||||||
|
var typeReference = _resolvedTypes[node.Variable.Type];
|
||||||
|
var variableDefinition = new VariableDefinition(typeReference);
|
||||||
|
_typedLocals.Add(node.Variable, variableDefinition);
|
||||||
|
ilProcessor.Body.Variables.Add(variableDefinition);
|
||||||
|
|
||||||
|
EmitExpression(node.Initializer, ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Stloc, variableDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
private void EmitExpressionStatement(BoundExpressionStatement node, ILProcessor ilProcessor)
|
private void EmitExpressionStatement(BoundExpressionStatement node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
EmitExpression(node.Expression, ilProcessor);
|
EmitExpression(node.Expression, ilProcessor);
|
||||||
@ -458,6 +531,9 @@ namespace Parser.Emitting
|
|||||||
case BoundNodeKind.BinaryOperationExpression:
|
case BoundNodeKind.BinaryOperationExpression:
|
||||||
EmitBinaryOperationExpression((BoundBinaryOperationExpression)node, ilProcessor);
|
EmitBinaryOperationExpression((BoundBinaryOperationExpression)node, ilProcessor);
|
||||||
break;
|
break;
|
||||||
|
case BoundNodeKind.ConversionExpression:
|
||||||
|
EmitConversionExpression((BoundConversionExpression)node, ilProcessor);
|
||||||
|
break;
|
||||||
case BoundNodeKind.FunctionCallExpression:
|
case BoundNodeKind.FunctionCallExpression:
|
||||||
EmitFunctionCallExpression((BoundFunctionCallExpression)node, ilProcessor);
|
EmitFunctionCallExpression((BoundFunctionCallExpression)node, ilProcessor);
|
||||||
break;
|
break;
|
||||||
@ -465,16 +541,47 @@ namespace Parser.Emitting
|
|||||||
EmitIdentifierNameExpression((BoundIdentifierNameExpression)node, ilProcessor);
|
EmitIdentifierNameExpression((BoundIdentifierNameExpression)node, ilProcessor);
|
||||||
break;
|
break;
|
||||||
case BoundNodeKind.NumberLiteralExpression:
|
case BoundNodeKind.NumberLiteralExpression:
|
||||||
EmitNumberLiteralExpression((BoundNumberLiteralExpression)node, ilProcessor);
|
EmitNumberLiteralExpression((BoundNumberDoubleLiteralExpression)node, ilProcessor);
|
||||||
break;
|
break;
|
||||||
case BoundNodeKind.StringLiteralExpression:
|
case BoundNodeKind.StringLiteralExpression:
|
||||||
EmitStringLiteralExpression((BoundStringLiteralExpression)node, ilProcessor);
|
EmitStringLiteralExpression((BoundStringLiteralExpression)node, ilProcessor);
|
||||||
break;
|
break;
|
||||||
|
case BoundNodeKind.TypedFunctionCallExpression:
|
||||||
|
EmitTypedFunctionCallExpression((BoundTypedFunctionCallExpression)node, ilProcessor);
|
||||||
|
break;
|
||||||
|
case BoundNodeKind.TypedVariableExpression:
|
||||||
|
EmitTypedVariableExpression((BoundTypedVariableExpression)node, ilProcessor);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"Invalid node kind '{node.Kind}'.");
|
throw new NotImplementedException($"Invalid node kind '{node.Kind}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void EmitConversionExpression(BoundConversionExpression node, ILProcessor ilProcessor)
|
||||||
|
{
|
||||||
|
var fromType = node.Expression.Type;
|
||||||
|
var toType = node.TargetType;
|
||||||
|
EmitExpression(node.Expression, ilProcessor);
|
||||||
|
if ((fromType, toType) == (TypeSymbol.Double, TypeSymbol.MObject))
|
||||||
|
{
|
||||||
|
ilProcessor.Emit(OpCodes.Call, _doubleToMObject);
|
||||||
|
}
|
||||||
|
else if ((fromType, toType) == (TypeSymbol.String, TypeSymbol.MObject))
|
||||||
|
{
|
||||||
|
ilProcessor.Emit(OpCodes.Call, _stringToMObject);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new NotImplementedException($"Conversion of '{fromType}' to '{toType}' is not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EmitTypedVariableExpression(BoundTypedVariableExpression node, ILProcessor ilProcessor)
|
||||||
|
{
|
||||||
|
var variableDefinition = _typedLocals[node.Variable];
|
||||||
|
ilProcessor.Emit(OpCodes.Ldloc, variableDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
private void EmitBinaryOperationExpression(BoundBinaryOperationExpression node, ILProcessor ilProcessor)
|
private void EmitBinaryOperationExpression(BoundBinaryOperationExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
var method = _binaryOperations[node.Op.Kind];
|
var method = _binaryOperations[node.Op.Kind];
|
||||||
@ -485,19 +592,39 @@ namespace Parser.Emitting
|
|||||||
|
|
||||||
private void EmitAssignmentExpression(BoundAssignmentExpression node, ILProcessor ilProcessor)
|
private void EmitAssignmentExpression(BoundAssignmentExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
if (node.Left.Kind != BoundNodeKind.IdentifierNameExpression)
|
var leftType = node.Left.Kind switch
|
||||||
|
{
|
||||||
|
BoundNodeKind.IdentifierNameExpression => TypeSymbol.MObject,
|
||||||
|
BoundNodeKind.TypedVariableExpression => ((BoundTypedVariableExpression)node.Left).Type,
|
||||||
|
_ => throw new Exception($"Assignment to lvalue of kind {node.Left.Kind} is not supported."),
|
||||||
|
};
|
||||||
|
|
||||||
|
var rightType = node.Right.Type;
|
||||||
|
|
||||||
|
var rewrittenRight = ConvertExpression(node.Right, leftType);
|
||||||
|
|
||||||
|
if (node.Left.Kind == BoundNodeKind.IdentifierNameExpression)
|
||||||
{
|
{
|
||||||
throw new Exception("Assignment to complex lvalues is not supported.");
|
|
||||||
}
|
|
||||||
var left = ((BoundIdentifierNameExpression)node.Left);
|
var left = ((BoundIdentifierNameExpression)node.Left);
|
||||||
ilProcessor.Emit(OpCodes.Ldloc_0);
|
ilProcessor.Emit(OpCodes.Ldloc_0);
|
||||||
ilProcessor.Emit(OpCodes.Ldstr, left.Name);
|
ilProcessor.Emit(OpCodes.Ldstr, left.Name);
|
||||||
EmitExpression(node.Right, ilProcessor);
|
EmitExpression(rewrittenRight, ilProcessor);
|
||||||
ilProcessor.Emit(OpCodes.Callvirt, _putItemIntoDictionary);
|
ilProcessor.Emit(OpCodes.Callvirt, _putItemIntoDictionary);
|
||||||
ilProcessor.Emit(OpCodes.Ldloc_0);
|
ilProcessor.Emit(OpCodes.Ldloc_0);
|
||||||
ilProcessor.Emit(OpCodes.Ldstr, left.Name);
|
ilProcessor.Emit(OpCodes.Ldstr, left.Name);
|
||||||
ilProcessor.Emit(OpCodes.Callvirt, _getItemFromDictionary);
|
ilProcessor.Emit(OpCodes.Callvirt, _getItemFromDictionary);
|
||||||
}
|
}
|
||||||
|
else if (node.Left.Kind == BoundNodeKind.TypedVariableExpression)
|
||||||
|
{
|
||||||
|
var typedVariableExpression = (BoundTypedVariableExpression)node.Left;
|
||||||
|
EmitExpression(rewrittenRight, ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Stloc, _typedLocals[typedVariableExpression.Variable]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"Assignment to lvalue of kind {node.Left.Kind} is not supported.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void EmitIdentifierNameExpression(BoundIdentifierNameExpression node, ILProcessor ilProcessor)
|
private void EmitIdentifierNameExpression(BoundIdentifierNameExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
@ -506,26 +633,109 @@ namespace Parser.Emitting
|
|||||||
ilProcessor.Emit(OpCodes.Callvirt, _getItemFromDictionary);
|
ilProcessor.Emit(OpCodes.Callvirt, _getItemFromDictionary);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitNumberLiteralExpression(BoundNumberLiteralExpression node, ILProcessor ilProcessor)
|
private void EmitNumberLiteralExpression(BoundNumberDoubleLiteralExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
ilProcessor.Emit(OpCodes.Ldc_R8, node.Value);
|
ilProcessor.Emit(OpCodes.Ldc_R8, node.Value);
|
||||||
ilProcessor.Emit(OpCodes.Call, _doubleToMObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitStringLiteralExpression(BoundStringLiteralExpression node, ILProcessor ilProcessor)
|
private void EmitStringLiteralExpression(BoundStringLiteralExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
ilProcessor.Emit(OpCodes.Ldstr, node.Value);
|
ilProcessor.Emit(OpCodes.Ldstr, node.Value);
|
||||||
ilProcessor.Emit(OpCodes.Call, _stringToMObject);
|
}
|
||||||
|
|
||||||
|
private BoundExpression? ConvertExpression(BoundExpression expression, TypeSymbol targetType)
|
||||||
|
{
|
||||||
|
var conversion = Conversion.Classify(expression.Type, targetType);
|
||||||
|
if (!conversion.Exists)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conversion.IsIdentity)
|
||||||
|
{
|
||||||
|
return expression;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return BoundNodeFactory.Conversion(expression.Syntax, targetType, expression);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoundExpression RewriteFunctionCall(BoundFunctionCallExpression node, TypedFunctionSymbol function)
|
||||||
|
{
|
||||||
|
var numberOfArguments = node.Arguments.Length;
|
||||||
|
if (numberOfArguments != function.Parameters.Length)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException($"Function '{function.Name}' expected {function.Parameters.Length} arguments, but was called with {numberOfArguments}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var rewrittenArguments = ImmutableArray.CreateBuilder<BoundExpression>(numberOfArguments);
|
||||||
|
for (var i = 0; i < numberOfArguments; i++)
|
||||||
|
{
|
||||||
|
var argument = node.Arguments[i];
|
||||||
|
var parameter = function.Parameters[i];
|
||||||
|
var rewrittenArgument = ConvertExpression(argument, parameter.Type);
|
||||||
|
if (rewrittenArgument is null)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException($"Argument number {i + 1} of function '{function.Name}' expects {parameter.Type}, but got {argument.Type}, and no conversion exists.");
|
||||||
|
|
||||||
|
}
|
||||||
|
rewrittenArguments.Add(rewrittenArgument);
|
||||||
|
}
|
||||||
|
|
||||||
|
return BoundNodeFactory.TypedFunctionCall(node.Syntax, function, rewrittenArguments.MoveToImmutable());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EmitTypedFunctionCallExpression(BoundTypedFunctionCallExpression node, ILProcessor ilProcessor)
|
||||||
|
{
|
||||||
|
var function = _builtInFunctions[node.Function];
|
||||||
|
foreach (var argument in node.Arguments)
|
||||||
|
{
|
||||||
|
EmitExpression(argument, ilProcessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
ilProcessor.Emit(OpCodes.Call, function);
|
||||||
|
if (node.Function.ReturnType == TypeSymbol.Void)
|
||||||
|
{
|
||||||
|
ilProcessor.Emit(OpCodes.Ldnull);
|
||||||
|
}
|
||||||
|
else if (node.Function.ReturnType == TypeSymbol.MObject)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception("Don't know how to cast function output.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitFunctionCallExpression(BoundFunctionCallExpression node, ILProcessor ilProcessor)
|
private void EmitFunctionCallExpression(BoundFunctionCallExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
if (node.Name.Kind == BoundNodeKind.IdentifierNameExpression
|
if (node.Name.Kind == BoundNodeKind.IdentifierNameExpression
|
||||||
&& ((BoundIdentifierNameExpression)node.Name).Name == "disp")
|
&& ((BoundIdentifierNameExpression)node.Name).Name == "disp")
|
||||||
|
{
|
||||||
|
var dispFunctionSymbol = BuiltInFunctions.Disp;
|
||||||
|
var rewrittenCall = RewriteFunctionCall(node, dispFunctionSymbol);
|
||||||
|
EmitExpression(rewrittenCall, ilProcessor);
|
||||||
|
//ilProcessor.Emit(OpCodes.Call, _dispReference);
|
||||||
|
//ilProcessor.Emit(OpCodes.Ldnull);
|
||||||
|
} else if (node.Name.Kind == BoundNodeKind.IdentifierNameExpression
|
||||||
|
&& ((BoundIdentifierNameExpression)node.Name).Name == "len")
|
||||||
{
|
{
|
||||||
EmitExpression(node.Arguments[0], ilProcessor);
|
EmitExpression(node.Arguments[0], ilProcessor);
|
||||||
ilProcessor.Emit(OpCodes.Call, _dispReference);
|
ilProcessor.Emit(OpCodes.Call, _lenReference);
|
||||||
ilProcessor.Emit(OpCodes.Ldnull);
|
}
|
||||||
|
else if (node.Name.Kind == BoundNodeKind.TypedVariableExpression)
|
||||||
|
{
|
||||||
|
if (node.Arguments.Length > 1)
|
||||||
|
{
|
||||||
|
throw new Exception("Multi-dimensional array slicing is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var typedVariableExpression = (BoundTypedVariableExpression)node.Name;
|
||||||
|
EmitTypedVariableExpression(typedVariableExpression, ilProcessor);
|
||||||
|
EmitExpression(node.Arguments[0], ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Call, _arraySliceReference);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -559,11 +769,11 @@ namespace Parser.Emitting
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private MethodInterfaceDescription ResolveFunction(BoundExpression expression)
|
private MethodInterfaceDescription ResolveFunction(BoundExpression node)
|
||||||
{
|
{
|
||||||
if (expression.Kind == BoundNodeKind.IdentifierNameExpression)
|
if (node.Kind == BoundNodeKind.IdentifierNameExpression)
|
||||||
{
|
{
|
||||||
var name = ((BoundIdentifierNameExpression)expression).Name;
|
var name = ((BoundIdentifierNameExpression)node).Name;
|
||||||
if (_functions.TryGetValue(name, out var result))
|
if (_functions.TryGetValue(name, out var result))
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
@ -574,7 +784,7 @@ namespace Parser.Emitting
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotImplementedException($"Dynamic functions calling not supported. Failed to resolve function call expression with kind '{expression.Kind}'.");
|
throw new NotImplementedException($"Dynamic functions calling not supported. Failed to resolve function call expression with kind '{node.Kind}'.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ namespace Parser
|
|||||||
BoundNodeKind.NamedFunctionHandleExpression =>
|
BoundNodeKind.NamedFunctionHandleExpression =>
|
||||||
EvaluateNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node),
|
EvaluateNamedFunctionHandleExpression((BoundNamedFunctionHandleExpression)node),
|
||||||
BoundNodeKind.NumberLiteralExpression =>
|
BoundNodeKind.NumberLiteralExpression =>
|
||||||
EvaluateNumberLiteralExpression((BoundNumberLiteralExpression)node),
|
EvaluateNumberLiteralExpression((BoundNumberDoubleLiteralExpression)node),
|
||||||
BoundNodeKind.StringLiteralExpression =>
|
BoundNodeKind.StringLiteralExpression =>
|
||||||
EvaluateStringLiteralExpression((BoundStringLiteralExpression)node),
|
EvaluateStringLiteralExpression((BoundStringLiteralExpression)node),
|
||||||
BoundNodeKind.UnaryOperationExpression =>
|
BoundNodeKind.UnaryOperationExpression =>
|
||||||
@ -420,7 +420,7 @@ namespace Parser
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private MObject? EvaluateNumberLiteralExpression(BoundNumberLiteralExpression node)
|
private MObject? EvaluateNumberLiteralExpression(BoundNumberDoubleLiteralExpression node)
|
||||||
{
|
{
|
||||||
return MObject.CreateDoubleNumber(node.Value);
|
return MObject.CreateDoubleNumber(node.Value);
|
||||||
}
|
}
|
||||||
|
@ -107,5 +107,10 @@ namespace Parser.Internal
|
|||||||
{
|
{
|
||||||
Report(span, $"Too many inputs in the call to '{functionName}'.");
|
Report(span, $"Too many inputs in the call to '{functionName}'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void ReportForLoopWithoutVariable(TextSpan span)
|
||||||
|
{
|
||||||
|
Report(span, $"A 'for' loop must have a loop variable.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,4 @@
|
|||||||
using Parser.Binding;
|
using Parser.Binding;
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -10,6 +9,7 @@ namespace Parser.Lowering
|
|||||||
internal class Lowerer : BoundTreeRewriter
|
internal class Lowerer : BoundTreeRewriter
|
||||||
{
|
{
|
||||||
private int _labelNumber = 0;
|
private int _labelNumber = 0;
|
||||||
|
private int _localVariableNumber = 0;
|
||||||
|
|
||||||
private Lowerer()
|
private Lowerer()
|
||||||
{
|
{
|
||||||
@ -21,6 +21,12 @@ namespace Parser.Lowering
|
|||||||
return new BoundLabel(name);
|
return new BoundLabel(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TypedVariableSymbol GenerateTypedLocalVariable(TypeSymbol typeSymbol)
|
||||||
|
{
|
||||||
|
var name = $"#{++_localVariableNumber}";
|
||||||
|
return new TypedVariableSymbol(name, typeSymbol);
|
||||||
|
}
|
||||||
|
|
||||||
public override BoundStatement RewriteIfStatement(BoundIfStatement node)
|
public override BoundStatement RewriteIfStatement(BoundIfStatement node)
|
||||||
{
|
{
|
||||||
// if cond
|
// if cond
|
||||||
@ -80,6 +86,84 @@ namespace Parser.Lowering
|
|||||||
return RewriteBlockStatement(Block(node.Syntax, builder.ToArray()));
|
return RewriteBlockStatement(Block(node.Syntax, builder.ToArray()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override BoundStatement RewriteForStatement(BoundForStatement node)
|
||||||
|
{
|
||||||
|
// for i = expr
|
||||||
|
// body
|
||||||
|
// end
|
||||||
|
//
|
||||||
|
// #array = expr
|
||||||
|
// #length = len(#array)
|
||||||
|
// #index = 0
|
||||||
|
// i = #array(#index);
|
||||||
|
// LabelLoop:
|
||||||
|
// gotoFalse (#index < #length) LabelEnd
|
||||||
|
// body
|
||||||
|
// #index = #index + 1
|
||||||
|
// goto LabelLoop
|
||||||
|
// LabelEnd:
|
||||||
|
var builder = ImmutableArray.CreateBuilder<BoundStatement>();
|
||||||
|
var labelLoop = GenerateLabel();
|
||||||
|
var labelEnd = GenerateLabel();
|
||||||
|
var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject);
|
||||||
|
var localLength = GenerateTypedLocalVariable(TypeSymbol.Int);
|
||||||
|
var localIndex = GenerateTypedLocalVariable(TypeSymbol.Int);
|
||||||
|
return RewriteBlockStatement(Block(
|
||||||
|
node.Syntax,
|
||||||
|
// #array = expr
|
||||||
|
TypedVariableDeclaration(node.Syntax, localArray, node.LoopedExpression),
|
||||||
|
// #length = len(#array)
|
||||||
|
TypedVariableDeclaration(
|
||||||
|
node.Syntax,
|
||||||
|
localLength,
|
||||||
|
FunctionCall(
|
||||||
|
node.Syntax,
|
||||||
|
Identifier(node.Syntax, "len"),
|
||||||
|
new[] { (BoundExpression)TypedVariableExpression(node.Syntax, localArray) }.ToImmutableArray())),
|
||||||
|
// #index = 0
|
||||||
|
TypedVariableDeclaration(node.Syntax, localIndex, NumberDoubleLiteral(node.Syntax, 0.0)),
|
||||||
|
// i = #array(#index);
|
||||||
|
ExpressionStatement(
|
||||||
|
node.Syntax,
|
||||||
|
Assignment(
|
||||||
|
node.Syntax,
|
||||||
|
node.LoopVariable,
|
||||||
|
FunctionCall(
|
||||||
|
node.Syntax,
|
||||||
|
TypedVariableExpression(node.Syntax, localArray),
|
||||||
|
new[] { (BoundExpression)TypedVariableExpression(node.Syntax, localIndex) }.ToImmutableArray())),
|
||||||
|
discardResult: true),
|
||||||
|
// LabelLoop:
|
||||||
|
LabelStatement(node.Syntax, labelLoop),
|
||||||
|
// gotoFalse (#index < #length) LabelEnd
|
||||||
|
GotoIfFalse(
|
||||||
|
node.Syntax,
|
||||||
|
BinaryOperation(
|
||||||
|
node.Syntax,
|
||||||
|
TypedVariableExpression(node.Syntax, localIndex),
|
||||||
|
BoundBinaryOperator.GetOperator(TokenKind.LessToken, TypeSymbol.Int, TypeSymbol.Int)!,
|
||||||
|
TypedVariableExpression(node.Syntax, localLength)),
|
||||||
|
labelEnd),
|
||||||
|
// body
|
||||||
|
node.Body,
|
||||||
|
// #index = #index + 1;
|
||||||
|
ExpressionStatement(
|
||||||
|
node.Syntax,
|
||||||
|
Assignment(
|
||||||
|
node.Syntax,
|
||||||
|
TypedVariableExpression(node.Syntax, localIndex),
|
||||||
|
BinaryOperation(
|
||||||
|
node.Syntax,
|
||||||
|
TypedVariableExpression(node.Syntax, localIndex),
|
||||||
|
BoundBinaryOperator.GetOperator(TokenKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int)!,
|
||||||
|
NumberIntLiteral(node.Syntax, 1))),
|
||||||
|
discardResult: true),
|
||||||
|
// goto LabelLoop
|
||||||
|
Goto(node.Syntax, labelLoop),
|
||||||
|
// LabelEnd:
|
||||||
|
LabelStatement(node.Syntax, labelEnd)));
|
||||||
|
}
|
||||||
|
|
||||||
public static BoundBlockStatement Lower(BoundStatement statement)
|
public static BoundBlockStatement Lower(BoundStatement statement)
|
||||||
{
|
{
|
||||||
var lowerer = new Lowerer();
|
var lowerer = new Lowerer();
|
||||||
|
@ -13,6 +13,18 @@ namespace Parser.MFunctions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static int Len(MObject? obj)
|
||||||
|
{
|
||||||
|
return obj switch
|
||||||
|
{
|
||||||
|
MDoubleMatrix m => m.RowCount * m.ColumnCount,
|
||||||
|
MDoubleNumber _ => 1,
|
||||||
|
MLogical _ => 1,
|
||||||
|
MCharArray c => c.Chars.Length,
|
||||||
|
_ => throw new System.Exception($"Unknown MObject type {obj.GetType()}"),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
public static bool ToBool(MObject operand)
|
public static bool ToBool(MObject operand)
|
||||||
{
|
{
|
||||||
return operand switch
|
return operand switch
|
||||||
@ -20,6 +32,7 @@ namespace Parser.MFunctions
|
|||||||
MDoubleNumber { Value: var value } => value != 0.0,
|
MDoubleNumber { Value: var value } => value != 0.0,
|
||||||
MLogical { Value: var value } => value,
|
MLogical { Value: var value } => value,
|
||||||
MCharArray { Chars: var value } => value.Length > 0,
|
MCharArray { Chars: var value } => value.Length > 0,
|
||||||
|
MDoubleMatrix m => m.RowCount > 0 && m.ColumnCount > 0,
|
||||||
_ => throw new System.Exception($"Unknown MObject type {operand.GetType()}"),
|
_ => throw new System.Exception($"Unknown MObject type {operand.GetType()}"),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,34 @@
|
|||||||
using Parser.Objects;
|
using Parser.Objects;
|
||||||
|
using System;
|
||||||
|
|
||||||
namespace Parser.MFunctions
|
namespace Parser.MFunctions
|
||||||
{
|
{
|
||||||
public static class MOperations
|
public static class MOperations
|
||||||
{
|
{
|
||||||
|
public static MObject? Colon(MObject left, MObject right)
|
||||||
|
{
|
||||||
|
if (left is MDoubleNumber { Value: var lValue }
|
||||||
|
&& right is MDoubleNumber { Value: var rValue })
|
||||||
|
{
|
||||||
|
var array = CreateRangeMatrix(lValue, rValue);
|
||||||
|
return MObject.CreateDoubleMatrix(array);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double[,] CreateRangeMatrix(double lValue, double rValue)
|
||||||
|
{
|
||||||
|
var length = (int)Math.Round(rValue - lValue) + 1;
|
||||||
|
var result = new double[1, length];
|
||||||
|
for (var i = 0; i < length; i++)
|
||||||
|
{
|
||||||
|
result[0, i] = lValue + i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
public static MObject? Plus(MObject left, MObject right)
|
public static MObject? Plus(MObject left, MObject right)
|
||||||
{
|
{
|
||||||
if (left is MDoubleNumber { Value: var lValue }
|
if (left is MDoubleNumber { Value: var lValue }
|
||||||
@ -101,5 +126,17 @@ namespace Parser.MFunctions
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MObject? ArraySlice(MObject array, MObject range)
|
||||||
|
{
|
||||||
|
if (array is MDoubleMatrix m
|
||||||
|
&& range is MDoubleNumber { Value: var doubleIndex })
|
||||||
|
{
|
||||||
|
var index = (int)doubleIndex;
|
||||||
|
return MObject.CreateDoubleNumber(m[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,50 @@
|
|||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
namespace Parser.Objects
|
namespace Parser.Objects
|
||||||
{
|
{
|
||||||
|
public class MDoubleMatrix : MObject
|
||||||
|
{
|
||||||
|
private MDoubleMatrix(double[,] matrix)
|
||||||
|
{
|
||||||
|
Matrix = matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[,] Matrix { get; }
|
||||||
|
|
||||||
|
public int RowCount { get; }
|
||||||
|
|
||||||
|
public int ColumnCount { get; }
|
||||||
|
|
||||||
|
public ref double this[int i, int j] => ref Matrix[i, j];
|
||||||
|
|
||||||
|
public ref double this[int i] => ref Matrix[i % RowCount, i / RowCount];
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
for (var i = 0; i < RowCount; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < ColumnCount; j++)
|
||||||
|
{
|
||||||
|
if (j > 0)
|
||||||
|
{
|
||||||
|
sb.Append(' ');
|
||||||
|
}
|
||||||
|
sb.Append(Matrix[i, j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MDoubleMatrix Create(double[,] matrix)
|
||||||
|
{
|
||||||
|
return new MDoubleMatrix(matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class MDoubleNumber : MObject
|
public class MDoubleNumber : MObject
|
||||||
{
|
{
|
||||||
private MDoubleNumber(double value)
|
private MDoubleNumber(double value)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
namespace Parser.Objects
|
using System;
|
||||||
|
|
||||||
|
namespace Parser.Objects
|
||||||
{
|
{
|
||||||
public abstract class MObject
|
public abstract class MObject
|
||||||
{
|
{
|
||||||
@ -7,6 +9,16 @@
|
|||||||
return MDoubleNumber.Create(value);
|
return MDoubleNumber.Create(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MDoubleNumber CreateIntNumber(int value)
|
||||||
|
{
|
||||||
|
return MDoubleNumber.Create(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MDoubleMatrix CreateDoubleMatrix(double[,] matrix)
|
||||||
|
{
|
||||||
|
return MDoubleMatrix.Create(matrix);
|
||||||
|
}
|
||||||
|
|
||||||
public static MCharArray CreateCharArray(char[] chars)
|
public static MCharArray CreateCharArray(char[] chars)
|
||||||
{
|
{
|
||||||
return MCharArray.Create(chars);
|
return MCharArray.Create(chars);
|
||||||
|
@ -5,6 +5,11 @@ f(x);
|
|||||||
x = 3;
|
x = 3;
|
||||||
f(x);
|
f(x);
|
||||||
|
|
||||||
|
% for i = 1:10
|
||||||
|
% disp(i);
|
||||||
|
% end
|
||||||
|
|
||||||
|
|
||||||
function f(x)
|
function f(x)
|
||||||
disp('X was');
|
disp('X was');
|
||||||
disp(x);
|
disp(x);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user