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) private BoundTryCatchStatement BindTryCatchStatement(TryCatchStatementSyntaxNode node)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
@ -290,6 +285,13 @@ namespace Parser.Binding
return Identifier(node, ((IdentifierNameExpressionSyntaxNode)node).Name.Text); 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) private BoundExpressionStatement BindExpressionStatement(ExpressionStatementSyntaxNode node)
{ {
var expression = BindExpression(node.Expression); var expression = BindExpression(node.Expression);

View File

@ -133,6 +133,14 @@ namespace Parser.Binding
return new BoundGotoStatement(syntax, label); 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( public static BoundIdentifierNameExpression Identifier(
SyntaxNode syntax, SyntaxNode syntax,
string name) string name)

View File

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

View File

@ -70,7 +70,9 @@ namespace Parser.Binding
public virtual BoundStatement RewriteWhileStatement(BoundWhileStatement node) 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) public virtual BoundStatement RewriteTryCatchStatement(BoundTryCatchStatement node)

View File

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

View File

@ -467,8 +467,13 @@ namespace Parser.Emitting
private void EmitConditionalGoto(BoundConditionalGotoStatement node, ILProcessor ilProcessor) private void EmitConditionalGoto(BoundConditionalGotoStatement node, ILProcessor ilProcessor)
{ {
EmitExpression(node.Condition, ilProcessor); var condition = ConvertExpression(node.Condition, TypeSymbol.Boolean);
ilProcessor.Emit(OpCodes.Call, _mObjectToBool); 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; var instruction = node.GotoIfTrue ? OpCodes.Brtrue : OpCodes.Brfalse;
if (_labels.TryGetValue(node.Label, out var target)) if (_labels.TryGetValue(node.Label, out var target))
{ {
@ -569,7 +574,7 @@ namespace Parser.Emitting
{ {
ilProcessor.Emit(OpCodes.Call, _doubleToMObject); 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); ilProcessor.Emit(OpCodes.Call, _intToMObject);
} }
@ -577,6 +582,10 @@ namespace Parser.Emitting
{ {
ilProcessor.Emit(OpCodes.Call, _stringToMObject); ilProcessor.Emit(OpCodes.Call, _stringToMObject);
} }
else if ((fromType, toType) == (TypeSymbol.MObject, TypeSymbol.Boolean))
{
ilProcessor.Emit(OpCodes.Call, _mObjectToBool);
}
else else
{ {
throw new NotImplementedException($"Conversion of '{fromType}' to '{toType}' is not implemented."); 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())); 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) public override BoundStatement RewriteForStatement(BoundForStatement node)
{ {
// for i = expr // for i = expr
@ -102,7 +137,6 @@ namespace Parser.Lowering
// #index = #index + 1 // #index = #index + 1
// goto LabelLoop // goto LabelLoop
// LabelEnd: // LabelEnd:
var builder = ImmutableArray.CreateBuilder<BoundStatement>();
var labelLoop = GenerateLabel(); var labelLoop = GenerateLabel();
var labelEnd = GenerateLabel(); var labelEnd = GenerateLabel();
var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject); var localArray = GenerateTypedLocalVariable(TypeSymbol.MObject);

View File

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