Reimplement For in terms of While
This commit is contained in:
parent
f66013cf12
commit
6f6bbfaa1c
@ -8,12 +8,12 @@ namespace Parser.Binding
|
||||
{
|
||||
new BoundBinaryOperator(
|
||||
TokenKind.LessToken,
|
||||
BoundBinaryOperatorKind.Less,
|
||||
BoundBinaryOperatorKind.LessInt,
|
||||
TypeSymbol.Int,
|
||||
TypeSymbol.Boolean),
|
||||
new BoundBinaryOperator(
|
||||
TokenKind.PlusToken,
|
||||
BoundBinaryOperatorKind.Plus,
|
||||
BoundBinaryOperatorKind.PlusInt,
|
||||
TypeSymbol.Int),
|
||||
};
|
||||
|
||||
|
@ -25,5 +25,7 @@
|
||||
Tilde,
|
||||
Caret,
|
||||
DotCaret,
|
||||
LessInt,
|
||||
PlusInt,
|
||||
}
|
||||
}
|
||||
|
@ -437,7 +437,7 @@ namespace Parser.Binding
|
||||
public ImmutableArray<BoundExpression> Arguments { get; }
|
||||
public override BoundNodeKind Kind => BoundNodeKind.FunctionCallExpression;
|
||||
|
||||
public override TypeSymbol Type => throw new System.NotImplementedException();
|
||||
public override TypeSymbol Type => TypeSymbol.MObject;
|
||||
}
|
||||
|
||||
public class BoundTypedFunctionCallExpression : BoundExpression
|
||||
|
@ -360,7 +360,6 @@ namespace Parser.Emitting
|
||||
|
||||
private void EmitFunction(LoweredFunction function, MethodDefinition methodDefinition)
|
||||
{
|
||||
Console.WriteLine($"Emitting function '{function.Name}'.");
|
||||
var ilProcessor = methodDefinition.Body.GetILProcessor();
|
||||
|
||||
_labels.Clear();
|
||||
@ -467,7 +466,7 @@ namespace Parser.Emitting
|
||||
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
var method = _binaryOperations[node.Op.Kind];
|
||||
if (_binaryOperations.TryGetValue(node.Op.Kind, out var method))
|
||||
{
|
||||
EmitExpression(node.Left, ilProcessor);
|
||||
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)
|
||||
@ -615,9 +634,11 @@ namespace Parser.Emitting
|
||||
_ => 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);
|
||||
var rewrittenRight = TryConvertExpression(node.Right, leftType);
|
||||
if (rewrittenRight is null)
|
||||
{
|
||||
throw new Exception($"Cannot convert an expression of type '{node.Right.Type}' to '{leftType}'.");
|
||||
}
|
||||
|
||||
if (node.Left.Kind == BoundNodeKind.IdentifierNameExpression)
|
||||
{
|
||||
@ -634,6 +655,7 @@ namespace Parser.Emitting
|
||||
{
|
||||
var typedVariableExpression = (BoundTypedVariableExpression)node.Left;
|
||||
EmitExpression(rewrittenRight, ilProcessor);
|
||||
ilProcessor.Emit(OpCodes.Dup);
|
||||
ilProcessor.Emit(OpCodes.Stloc, _typedLocals[typedVariableExpression.Variable]);
|
||||
}
|
||||
else
|
||||
@ -664,7 +686,7 @@ namespace Parser.Emitting
|
||||
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);
|
||||
if (!conversion.Exists)
|
||||
@ -680,7 +702,12 @@ namespace Parser.Emitting
|
||||
{
|
||||
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)
|
||||
@ -696,7 +723,7 @@ namespace Parser.Emitting
|
||||
{
|
||||
var argument = node.Arguments[i];
|
||||
var parameter = function.Parameters[i];
|
||||
var rewrittenArgument = ConvertExpression(argument, parameter.Type);
|
||||
var rewrittenArgument = TryConvertExpression(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.");
|
||||
@ -753,9 +780,10 @@ namespace Parser.Emitting
|
||||
throw new Exception("Multi-dimensional array slicing is not supported.");
|
||||
}
|
||||
|
||||
var typedVariableExpression = (BoundTypedVariableExpression)node.Name;
|
||||
EmitTypedVariableExpression(typedVariableExpression, ilProcessor);
|
||||
EmitExpression(node.Arguments[0], ilProcessor);
|
||||
var typedVariableExpression = ConvertExpression((BoundTypedVariableExpression)node.Name, TypeSymbol.MObject);
|
||||
EmitExpression(typedVariableExpression, ilProcessor);
|
||||
var indexExpression = ConvertExpression(node.Arguments[0], TypeSymbol.MObject);
|
||||
EmitExpression(indexExpression, ilProcessor);
|
||||
ilProcessor.Emit(OpCodes.Call, _arraySliceReference);
|
||||
}
|
||||
else
|
||||
|
@ -1,4 +1,5 @@
|
||||
using Parser.Binding;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
@ -127,35 +128,22 @@ namespace Parser.Lowering
|
||||
// body
|
||||
// end
|
||||
//
|
||||
// |
|
||||
// |
|
||||
// V
|
||||
//
|
||||
// #array = expr
|
||||
// #length = len(#array)
|
||||
// #index = 0
|
||||
// while #index < #length
|
||||
// i = #array(#index);
|
||||
// LabelLoop:
|
||||
// gotoFalse (#index < #length) LabelEnd
|
||||
// body
|
||||
// #index = #index + 1
|
||||
// goto LabelLoop
|
||||
// LabelEnd:
|
||||
var labelLoop = GenerateLabel();
|
||||
var labelEnd = GenerateLabel();
|
||||
var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject);
|
||||
var localLength = GenerateTypedLocalVariable(TypeSymbol.Int);
|
||||
var localIndex = GenerateTypedLocalVariable(TypeSymbol.Int);
|
||||
return RewriteBlockStatement(Block(
|
||||
var whileBody = 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,
|
||||
@ -167,17 +155,6 @@ namespace Parser.Lowering
|
||||
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;
|
||||
@ -191,11 +168,33 @@ namespace Parser.Lowering
|
||||
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)));
|
||||
discardResult: true));
|
||||
|
||||
var result = 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, 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)
|
||||
|
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.Text;
|
||||
|
||||
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
|
||||
{
|
||||
private MDoubleNumber(double value)
|
||||
|
@ -5,16 +5,15 @@ f(x);
|
||||
x = 3;
|
||||
f(x);
|
||||
|
||||
i = 1;
|
||||
while i <= 10
|
||||
disp(i);
|
||||
i = i + 1;
|
||||
end
|
||||
|
||||
% for i = 1:10
|
||||
% i = 1;
|
||||
% while i <= 10
|
||||
% disp(i);
|
||||
% i = i + 1;
|
||||
% end
|
||||
|
||||
for i = 1:10
|
||||
disp(i);
|
||||
end
|
||||
|
||||
function f(x)
|
||||
disp('X was');
|
||||
|
Loading…
x
Reference in New Issue
Block a user