Reimplement For in terms of While
This commit is contained in:
parent
f66013cf12
commit
6f6bbfaa1c
@ -8,12 +8,12 @@ namespace Parser.Binding
|
|||||||
{
|
{
|
||||||
new BoundBinaryOperator(
|
new BoundBinaryOperator(
|
||||||
TokenKind.LessToken,
|
TokenKind.LessToken,
|
||||||
BoundBinaryOperatorKind.Less,
|
BoundBinaryOperatorKind.LessInt,
|
||||||
TypeSymbol.Int,
|
TypeSymbol.Int,
|
||||||
TypeSymbol.Boolean),
|
TypeSymbol.Boolean),
|
||||||
new BoundBinaryOperator(
|
new BoundBinaryOperator(
|
||||||
TokenKind.PlusToken,
|
TokenKind.PlusToken,
|
||||||
BoundBinaryOperatorKind.Plus,
|
BoundBinaryOperatorKind.PlusInt,
|
||||||
TypeSymbol.Int),
|
TypeSymbol.Int),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -25,5 +25,7 @@
|
|||||||
Tilde,
|
Tilde,
|
||||||
Caret,
|
Caret,
|
||||||
DotCaret,
|
DotCaret,
|
||||||
|
LessInt,
|
||||||
|
PlusInt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,7 +437,7 @@ namespace Parser.Binding
|
|||||||
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 override TypeSymbol Type => TypeSymbol.MObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BoundTypedFunctionCallExpression : BoundExpression
|
public class BoundTypedFunctionCallExpression : BoundExpression
|
||||||
|
@ -360,7 +360,6 @@ 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();
|
||||||
@ -467,7 +466,7 @@ namespace Parser.Emitting
|
|||||||
|
|
||||||
private void EmitConditionalGoto(BoundConditionalGotoStatement node, ILProcessor ilProcessor)
|
private void EmitConditionalGoto(BoundConditionalGotoStatement node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
var condition = ConvertExpression(node.Condition, TypeSymbol.Boolean);
|
var condition = TryConvertExpression(node.Condition, TypeSymbol.Boolean);
|
||||||
if (condition is null)
|
if (condition is null)
|
||||||
{
|
{
|
||||||
throw new Exception("Cannot cast a condition in GOTO to boolean.");
|
throw new Exception("Cannot cast a condition in GOTO to boolean.");
|
||||||
@ -600,10 +599,30 @@ namespace Parser.Emitting
|
|||||||
|
|
||||||
private void EmitBinaryOperationExpression(BoundBinaryOperationExpression node, ILProcessor ilProcessor)
|
private void EmitBinaryOperationExpression(BoundBinaryOperationExpression node, ILProcessor ilProcessor)
|
||||||
{
|
{
|
||||||
var method = _binaryOperations[node.Op.Kind];
|
if (_binaryOperations.TryGetValue(node.Op.Kind, out var method))
|
||||||
EmitExpression(node.Left, ilProcessor);
|
{
|
||||||
EmitExpression(node.Right, ilProcessor);
|
EmitExpression(node.Left, ilProcessor);
|
||||||
ilProcessor.Emit(OpCodes.Call, method);
|
EmitExpression(node.Right, ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Call, method);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (node.Op.Kind == BoundBinaryOperatorKind.LessInt)
|
||||||
|
{
|
||||||
|
EmitExpression(node.Left, ilProcessor);
|
||||||
|
EmitExpression(node.Right, ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Clt);
|
||||||
|
}
|
||||||
|
else if (node.Op.Kind == BoundBinaryOperatorKind.PlusInt)
|
||||||
|
{
|
||||||
|
EmitExpression(node.Left, ilProcessor);
|
||||||
|
EmitExpression(node.Right, ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Add);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new Exception($"Binary operation '{node.Op.Kind}' not implemented.");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitAssignmentExpression(BoundAssignmentExpression node, ILProcessor ilProcessor)
|
private void EmitAssignmentExpression(BoundAssignmentExpression node, ILProcessor ilProcessor)
|
||||||
@ -615,9 +634,11 @@ namespace Parser.Emitting
|
|||||||
_ => throw new Exception($"Assignment to lvalue of kind {node.Left.Kind} is not supported."),
|
_ => throw new Exception($"Assignment to lvalue of kind {node.Left.Kind} is not supported."),
|
||||||
};
|
};
|
||||||
|
|
||||||
var rightType = node.Right.Type;
|
var rewrittenRight = TryConvertExpression(node.Right, leftType);
|
||||||
|
if (rewrittenRight is null)
|
||||||
var rewrittenRight = ConvertExpression(node.Right, leftType);
|
{
|
||||||
|
throw new Exception($"Cannot convert an expression of type '{node.Right.Type}' to '{leftType}'.");
|
||||||
|
}
|
||||||
|
|
||||||
if (node.Left.Kind == BoundNodeKind.IdentifierNameExpression)
|
if (node.Left.Kind == BoundNodeKind.IdentifierNameExpression)
|
||||||
{
|
{
|
||||||
@ -634,6 +655,7 @@ namespace Parser.Emitting
|
|||||||
{
|
{
|
||||||
var typedVariableExpression = (BoundTypedVariableExpression)node.Left;
|
var typedVariableExpression = (BoundTypedVariableExpression)node.Left;
|
||||||
EmitExpression(rewrittenRight, ilProcessor);
|
EmitExpression(rewrittenRight, ilProcessor);
|
||||||
|
ilProcessor.Emit(OpCodes.Dup);
|
||||||
ilProcessor.Emit(OpCodes.Stloc, _typedLocals[typedVariableExpression.Variable]);
|
ilProcessor.Emit(OpCodes.Stloc, _typedLocals[typedVariableExpression.Variable]);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -664,7 +686,7 @@ namespace Parser.Emitting
|
|||||||
ilProcessor.Emit(OpCodes.Ldstr, node.Value);
|
ilProcessor.Emit(OpCodes.Ldstr, node.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression? ConvertExpression(BoundExpression expression, TypeSymbol targetType)
|
private BoundExpression? TryConvertExpression(BoundExpression expression, TypeSymbol targetType)
|
||||||
{
|
{
|
||||||
var conversion = Conversion.Classify(expression.Type, targetType);
|
var conversion = Conversion.Classify(expression.Type, targetType);
|
||||||
if (!conversion.Exists)
|
if (!conversion.Exists)
|
||||||
@ -680,7 +702,12 @@ namespace Parser.Emitting
|
|||||||
{
|
{
|
||||||
return BoundNodeFactory.Conversion(expression.Syntax, targetType, expression);
|
return BoundNodeFactory.Conversion(expression.Syntax, targetType, expression);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private BoundExpression ConvertExpression(BoundExpression expression, TypeSymbol targetType)
|
||||||
|
{
|
||||||
|
return TryConvertExpression(expression, targetType)
|
||||||
|
?? throw new Exception($"Conversion from '{expression.Type}' to '{targetType}' failed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private BoundExpression RewriteFunctionCall(BoundFunctionCallExpression node, TypedFunctionSymbol function)
|
private BoundExpression RewriteFunctionCall(BoundFunctionCallExpression node, TypedFunctionSymbol function)
|
||||||
@ -696,7 +723,7 @@ namespace Parser.Emitting
|
|||||||
{
|
{
|
||||||
var argument = node.Arguments[i];
|
var argument = node.Arguments[i];
|
||||||
var parameter = function.Parameters[i];
|
var parameter = function.Parameters[i];
|
||||||
var rewrittenArgument = ConvertExpression(argument, parameter.Type);
|
var rewrittenArgument = TryConvertExpression(argument, parameter.Type);
|
||||||
if (rewrittenArgument is null)
|
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.");
|
throw new NotImplementedException($"Argument number {i + 1} of function '{function.Name}' expects {parameter.Type}, but got {argument.Type}, and no conversion exists.");
|
||||||
@ -753,9 +780,10 @@ namespace Parser.Emitting
|
|||||||
throw new Exception("Multi-dimensional array slicing is not supported.");
|
throw new Exception("Multi-dimensional array slicing is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
var typedVariableExpression = (BoundTypedVariableExpression)node.Name;
|
var typedVariableExpression = ConvertExpression((BoundTypedVariableExpression)node.Name, TypeSymbol.MObject);
|
||||||
EmitTypedVariableExpression(typedVariableExpression, ilProcessor);
|
EmitExpression(typedVariableExpression, ilProcessor);
|
||||||
EmitExpression(node.Arguments[0], ilProcessor);
|
var indexExpression = ConvertExpression(node.Arguments[0], TypeSymbol.MObject);
|
||||||
|
EmitExpression(indexExpression, ilProcessor);
|
||||||
ilProcessor.Emit(OpCodes.Call, _arraySliceReference);
|
ilProcessor.Emit(OpCodes.Call, _arraySliceReference);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Parser.Binding;
|
using Parser.Binding;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@ -127,36 +128,23 @@ namespace Parser.Lowering
|
|||||||
// body
|
// body
|
||||||
// end
|
// end
|
||||||
//
|
//
|
||||||
|
// |
|
||||||
|
// |
|
||||||
|
// V
|
||||||
|
//
|
||||||
// #array = expr
|
// #array = expr
|
||||||
// #length = len(#array)
|
// #length = len(#array)
|
||||||
// #index = 0
|
// #index = 0
|
||||||
// i = #array(#index);
|
// while #index < #length
|
||||||
// LabelLoop:
|
// i = #array(#index);
|
||||||
// gotoFalse (#index < #length) LabelEnd
|
// body
|
||||||
// body
|
// #index = #index + 1
|
||||||
// #index = #index + 1
|
|
||||||
// goto LabelLoop
|
|
||||||
// LabelEnd:
|
|
||||||
var labelLoop = GenerateLabel();
|
|
||||||
var labelEnd = GenerateLabel();
|
|
||||||
var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject);
|
var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject);
|
||||||
var localLength = GenerateTypedLocalVariable(TypeSymbol.Int);
|
var localLength = GenerateTypedLocalVariable(TypeSymbol.Int);
|
||||||
var localIndex = GenerateTypedLocalVariable(TypeSymbol.Int);
|
var localIndex = GenerateTypedLocalVariable(TypeSymbol.Int);
|
||||||
return RewriteBlockStatement(Block(
|
var whileBody = Block(
|
||||||
node.Syntax,
|
node.Syntax,
|
||||||
// #array = expr
|
// i = #array(#index);
|
||||||
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(
|
ExpressionStatement(
|
||||||
node.Syntax,
|
node.Syntax,
|
||||||
Assignment(
|
Assignment(
|
||||||
@ -167,18 +155,7 @@ namespace Parser.Lowering
|
|||||||
TypedVariableExpression(node.Syntax, localArray),
|
TypedVariableExpression(node.Syntax, localArray),
|
||||||
new[] { (BoundExpression)TypedVariableExpression(node.Syntax, localIndex) }.ToImmutableArray())),
|
new[] { (BoundExpression)TypedVariableExpression(node.Syntax, localIndex) }.ToImmutableArray())),
|
||||||
discardResult: true),
|
discardResult: true),
|
||||||
// LabelLoop:
|
// body
|
||||||
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,
|
node.Body,
|
||||||
// #index = #index + 1;
|
// #index = #index + 1;
|
||||||
ExpressionStatement(
|
ExpressionStatement(
|
||||||
@ -191,11 +168,33 @@ namespace Parser.Lowering
|
|||||||
TypedVariableExpression(node.Syntax, localIndex),
|
TypedVariableExpression(node.Syntax, localIndex),
|
||||||
BoundBinaryOperator.GetOperator(TokenKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int)!,
|
BoundBinaryOperator.GetOperator(TokenKind.PlusToken, TypeSymbol.Int, TypeSymbol.Int)!,
|
||||||
NumberIntLiteral(node.Syntax, 1))),
|
NumberIntLiteral(node.Syntax, 1))),
|
||||||
discardResult: true),
|
discardResult: true));
|
||||||
// goto LabelLoop
|
|
||||||
Goto(node.Syntax, labelLoop),
|
var result = Block(
|
||||||
// LabelEnd:
|
node.Syntax,
|
||||||
LabelStatement(node.Syntax, labelEnd)));
|
// #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, NumberIntLiteral(node.Syntax, 0)),
|
||||||
|
// while #index < #length
|
||||||
|
// whileBody
|
||||||
|
WhileStatement(
|
||||||
|
node.Syntax,
|
||||||
|
BinaryOperation(
|
||||||
|
node.Syntax,
|
||||||
|
TypedVariableExpression(node.Syntax, localIndex),
|
||||||
|
BoundBinaryOperator.GetOperator(TokenKind.LessToken, TypeSymbol.Int, TypeSymbol.Int)!,
|
||||||
|
TypedVariableExpression(node.Syntax, localLength)),
|
||||||
|
whileBody));
|
||||||
|
return RewriteBlockStatement(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BoundBlockStatement Lower(BoundStatement statement)
|
public static BoundBlockStatement Lower(BoundStatement statement)
|
||||||
|
48
Parser/Objects/MDoubleMatrix.cs
Normal file
48
Parser/Objects/MDoubleMatrix.cs
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Parser.Objects
|
||||||
|
{
|
||||||
|
public class MDoubleMatrix : MObject
|
||||||
|
{
|
||||||
|
private MDoubleMatrix(double[,] matrix)
|
||||||
|
{
|
||||||
|
Matrix = matrix;
|
||||||
|
RowCount = matrix.GetLength(0);
|
||||||
|
ColumnCount = matrix.GetLength(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,50 +1,7 @@
|
|||||||
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)
|
||||||
|
@ -5,16 +5,15 @@ f(x);
|
|||||||
x = 3;
|
x = 3;
|
||||||
f(x);
|
f(x);
|
||||||
|
|
||||||
i = 1;
|
% i = 1;
|
||||||
while i <= 10
|
% while i <= 10
|
||||||
disp(i);
|
|
||||||
i = i + 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
% for i = 1:10
|
|
||||||
% disp(i);
|
% disp(i);
|
||||||
|
% i = i + 1;
|
||||||
% end
|
% end
|
||||||
|
|
||||||
|
for i = 1:10
|
||||||
|
disp(i);
|
||||||
|
end
|
||||||
|
|
||||||
function f(x)
|
function f(x)
|
||||||
disp('X was');
|
disp('X was');
|
||||||
|
Loading…
x
Reference in New Issue
Block a user