Implement While

This commit is contained in:
Alexander Luzgarev 2020-07-20 14:02:39 +02:00
parent 52198147e2
commit f66013cf12
8 changed files with 83 additions and 11 deletions

View File

@ -132,11 +132,6 @@ namespace Parser.Binding
};
}
private BoundWhileStatement BindWhileStatement(WhileStatementSyntaxNode node)
{
throw new NotImplementedException();
}
private BoundTryCatchStatement BindTryCatchStatement(TryCatchStatementSyntaxNode node)
{
throw new NotImplementedException();
@ -290,6 +285,13 @@ namespace Parser.Binding
return Identifier(node, ((IdentifierNameExpressionSyntaxNode)node).Name.Text);
}
private BoundWhileStatement BindWhileStatement(WhileStatementSyntaxNode node)
{
var condition = BindConversion(BindExpression(node.Condition), TypeSymbol.Boolean);
var body = BindStatement(node.Body);
return WhileStatement(node, condition, body);
}
private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node)
{
var expression = BindExpression(node.Expression);

View File

@ -133,6 +133,14 @@ namespace Parser.Binding
return new BoundGotoStatement(syntax, label);
}
public static BoundWhileStatement WhileStatement(
SyntaxNode syntax,
BoundExpression condition,
BoundStatement body)
{
return new BoundWhileStatement(syntax, condition, body);
}
public static BoundIdentifierNameExpression Identifier(
SyntaxNode syntax,
string name)

View File

@ -256,12 +256,18 @@ namespace Parser.Binding
public class BoundWhileStatement : BoundStatement
{
public BoundWhileStatement(SyntaxNode syntax)
public BoundWhileStatement(SyntaxNode syntax, BoundExpression condition, BoundStatement body)
: base(syntax)
{
Condition = condition;
Body = body;
}
public override BoundNodeKind Kind => BoundNodeKind.WhileStatement;
public BoundExpression Condition { get; }
public BoundStatement Body { get; }
}
public abstract class BoundExpression : BoundNode

View File

@ -70,7 +70,9 @@ namespace Parser.Binding
public virtual BoundStatement RewriteWhileStatement(BoundWhileStatement node)
{
throw new NotImplementedException();
var condition = RewriteExpression(node.Condition);
var body = RewriteStatement(node.Body);
return WhileStatement(node.Syntax, condition, body);
}
public virtual BoundStatement RewriteTryCatchStatement(BoundTryCatchStatement node)

View File

@ -28,6 +28,11 @@
return Implicit;
}
if (to == TypeSymbol.Boolean)
{
return Implicit;
}
return None;
}
}

View File

@ -467,8 +467,13 @@ namespace Parser.Emitting
private void EmitConditionalGoto(BoundConditionalGotoStatement node, ILProcessor ilProcessor)
{
EmitExpression(node.Condition, ilProcessor);
ilProcessor.Emit(OpCodes.Call, _mObjectToBool);
var condition = ConvertExpression(node.Condition, TypeSymbol.Boolean);
if (condition is null)
{
throw new Exception("Cannot cast a condition in GOTO to boolean.");
}
EmitExpression(condition, ilProcessor);
var instruction = node.GotoIfTrue ? OpCodes.Brtrue : OpCodes.Brfalse;
if (_labels.TryGetValue(node.Label, out var target))
{
@ -569,7 +574,7 @@ namespace Parser.Emitting
{
ilProcessor.Emit(OpCodes.Call, _doubleToMObject);
}
if ((fromType, toType) == (TypeSymbol.Int, TypeSymbol.MObject))
else if ((fromType, toType) == (TypeSymbol.Int, TypeSymbol.MObject))
{
ilProcessor.Emit(OpCodes.Call, _intToMObject);
}
@ -577,6 +582,10 @@ namespace Parser.Emitting
{
ilProcessor.Emit(OpCodes.Call, _stringToMObject);
}
else if ((fromType, toType) == (TypeSymbol.MObject, TypeSymbol.Boolean))
{
ilProcessor.Emit(OpCodes.Call, _mObjectToBool);
}
else
{
throw new NotImplementedException($"Conversion of '{fromType}' to '{toType}' is not implemented.");

View File

@ -86,6 +86,41 @@ namespace Parser.Lowering
return RewriteBlockStatement(Block(node.Syntax, builder.ToArray()));
}
public override BoundStatement RewriteWhileStatement(BoundWhileStatement node)
{
// while cond
// body
// end
//
// |
// |
// V
//
// LabelLoop:
// gotoFalse cond LabelEnd
// body
// goto LabelLoop
// LabelEnd:
var labelLoop = GenerateLabel();
var labelEnd = GenerateLabel();
var result = Block(
node.Syntax,
// LabelLoop:
LabelStatement(node.Syntax, labelLoop),
// gotoFalse cond LabelEnd
GotoIfFalse(
node.Syntax,
node.Condition,
labelEnd),
// body
node.Body,
// goto LabelLoop
Goto(node.Syntax, labelLoop),
// LabelEnd:
LabelStatement(node.Syntax, labelEnd));
return RewriteBlockStatement(result);
}
public override BoundStatement RewriteForStatement(BoundForStatement node)
{
// for i = expr
@ -102,7 +137,6 @@ namespace Parser.Lowering
// #index = #index + 1
// goto LabelLoop
// LabelEnd:
var builder = ImmutableArray.CreateBuilder<BoundStatement>();
var labelLoop = GenerateLabel();
var labelEnd = GenerateLabel();
var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject);

View File

@ -5,6 +5,12 @@ f(x);
x = 3;
f(x);
i = 1;
while i <= 10
disp(i);
i = i + 1;
end
% for i = 1:10
% disp(i);
% end