Implement While
This commit is contained in:
parent
52198147e2
commit
f66013cf12
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -28,6 +28,11 @@
|
||||
return Implicit;
|
||||
}
|
||||
|
||||
if (to == TypeSymbol.Boolean)
|
||||
{
|
||||
return Implicit;
|
||||
}
|
||||
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
@ -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.");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user