Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enh(directx): Add do-while loop support to DirectX backend #206

Merged
merged 3 commits into from
Oct 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions crosstl/src/backend/DirectX/DirectxAst.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,15 @@ def __repr__(self):
return f"WhileNode(condition={self.condition}, body={self.body})"


class DoWhileNode(ASTNode):
def __init__(self, condition, body):
self.condition = condition
self.body = body

def __repr__(self):
return f"DoWhileNode(condition={self.condition}, body={self.body})"


class ReturnNode(ASTNode):
def __init__(self, value):
self.value = value
Expand Down
11 changes: 11 additions & 0 deletions crosstl/src/backend/DirectX/DirectxCrossGLCodeGen.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ def generate_function_body(self, body, indent=0, is_main=False):
code += self.generate_for_loop(stmt, indent, is_main)
elif isinstance(stmt, WhileNode):
code += self.generate_while_loop(stmt, indent, is_main)
elif isinstance(stmt, DoWhileNode):
code += self.generate_do_while_loop(stmt, indent, is_main)
elif isinstance(stmt, IfNode):
code += self.generate_if_statement(stmt, indent, is_main)
return code
Expand All @@ -164,6 +166,15 @@ def generate_while_loop(self, node, indent, is_main):
code += " " * indent + "}\n"
return code

def generate_do_while_loop(self, node, indent, is_main):
condition = self.generate_expression(node.condition, is_main)

code = "do {\n"
code += self.generate_function_body(node.body, indent + 1, is_main)
code += " " * indent + "} "
code += f"while ({condition});\n"
return code

def generate_if_statement(self, node, indent, is_main):
condition = self.generate_expression(node.condition, is_main)

Expand Down
2 changes: 2 additions & 0 deletions crosstl/src/backend/DirectX/DirectxLexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
("ELSE", r"\belse\b"),
("FOR", r"\bfor\b"),
("WHILE", r"\b\while\b"),
("DO", r"\b\do\b"),
("REGISTER", r"\bregister\b"),
("IDENTIFIER", r"[a-zA-Z_][a-zA-Z0-9_]*"),
("NUMBER", r"\d+(\.\d+)?"),
Expand Down Expand Up @@ -74,6 +75,7 @@
"else": "ELSE",
"for": "FOR",
"while": "WHILE",
"do": "DO",
"register": "REGISTER",
}

Expand Down
19 changes: 19 additions & 0 deletions crosstl/src/backend/DirectX/DirectxParser.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
BinaryOpNode,
ForNode,
WhileNode,
DoWhileNode,
FunctionCallNode,
FunctionNode,
IfNode,
Expand Down Expand Up @@ -198,6 +199,8 @@ def parse_statement(self):
return self.parse_return_statement()
elif self.current_token[0] == "WHILE":
return self.parse_while_statement()
elif self.current_token[0] == "DO":
return self.parse_do_while_statement()
else:
return self.parse_expression_statement()

Expand Down Expand Up @@ -356,6 +359,22 @@ def parse_while_statement(self):

return WhileNode(condition, body)

def parse_do_while_statement(self):
# do token
self.eat("DO")

# parse do block
body = self.parse_block()

# parse while condition
self.eat("WHILE")
self.eat("LPAREN")
condition = self.parse_expression()
self.eat("RPAREN")
self.eat("SEMICOLON")

return DoWhileNode(condition, body)

def parse_return_statement(self):
self.eat("RETURN")
value = self.parse_expression()
Expand Down
45 changes: 45 additions & 0 deletions tests/test_backend/test_directx/test_codegen.py
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,51 @@ def test_while_codegen():
pytest.fail("While loop parsing or code generation not implemented.")


def test_do_while_codegen():
code = """
struct VSInput {
float4 position : POSITION;
float4 color : TEXCOORD0;
};
struct VSOutput {
float4 out_position : TEXCOORD0;
};
VSOutput VSMain(VSInput input) {
VSOutput output;
output.out_position = input.position;
int i = 0;
do {
output.out_position = input.color;
i = i + 1; // Increment the loop variable
} while (i < 10);
return output;
}
struct PSInput {
float4 in_position : TEXCOORD0;
};
struct PSOutput {
float4 out_color : SV_TARGET0;
};
PSOutput PSMain(PSInput input) {
PSOutput output;
output.out_color = input.in_position;
int i = 0;
do {
output.out_color = float4(1.0, 1.0, 1.0, 1.0);
i = i + 1; // Increment the loop variable
} while (i < 10);
return output;
}
"""
try:
tokens = tokenize_code(code)
ast = parse_code(tokens)
generated_code = generate_code(ast)
print(generated_code)
except SyntaxError:
pytest.fail("While loop parsing or code generation not implemented.")


def test_else_codegen():
code = """
struct VSInput {
Expand Down
19 changes: 19 additions & 0 deletions tests/test_backend/test_directx/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@ def test_while_parsing():
pytest.fail("while parsing not implemented")


def test_do_while_parsing():
code = """
VSOutput VSMain(VSInput input) {
VSOutput output;
int i = 0;
do {
output.out_position = input.position;
i = i + 1;
} while (i < 10);
return output;
}
"""
try:
tokens = tokenize_code(code)
parse_code(tokens)
except SyntaxError:
pytest.fail("do while parsing not implemented")


def test_else_parsing():
code = """
PSOutput PSMain(PSInput input) {
Expand Down
Loading