chmod a-x
[mesa.git] / src / mesa / shader / slang / slang_assemble_conditional.c
index 115e292609e2a6d8eb0353d268d7688e3a01adb5..f3400e8753a8a257e43a6dcc06dc348f4bef4eac 100644 (file)
-/*\r
- * Mesa 3-D graphics library\r
- * Version:  6.5\r
- *\r
- * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.\r
- *\r
- * Permission is hereby granted, free of charge, to any person obtaining a\r
- * copy of this software and associated documentation files (the "Software"),\r
- * to deal in the Software without restriction, including without limitation\r
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
- * and/or sell copies of the Software, and to permit persons to whom the\r
- * Software is furnished to do so, subject to the following conditions:\r
- *\r
- * The above copyright notice and this permission notice shall be included\r
- * in all copies or substantial portions of the Software.\r
- *\r
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS\r
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL\r
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\r
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
- */\r
-\r
-/**\r
- * \file slang_assemble_conditional.c\r
- * slang condtional expressions assembler\r
- * \author Michal Krol\r
- */\r
-\r
-#include "imports.h"\r
-#include "slang_utility.h"\r
-#include "slang_assemble_conditional.h"\r
-#include "slang_assemble.h"\r
-#include "slang_execute.h"\r
-\r
-/*\r
- * _slang_assemble_logicaland()\r
- *\r
- * and:\r
- *    <left-expression>\r
- *    jumpz zero\r
- *    <right-expression>\r
- *    jump end\r
- *    zero:\r
- *    push 0\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_logicaland (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint zero_jump, end_jump;\r
-\r
-       /* evaluate left expression */\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to pushing 0 if not true */\r
-       zero_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* evaluate right expression */\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the end of the expression */\r
-       end_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* push 0 on stack */\r
-       A->file->code[zero_jump].param[0] = A->file->count;\r
-       if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 0))\r
-               return GL_FALSE;\r
-\r
-       /* the end of the expression */\r
-       A->file->code[end_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
-/*\r
- * _slang_assemble_logicalor()\r
- *\r
- * or:\r
- *    <left-expression>\r
- *    jumpz right\r
- *    push 1\r
- *    jump end\r
- * right:\r
- *    <right-expression>\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_logicalor (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint right_jump, end_jump;\r
-\r
-       /* evaluate left expression */\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to evaluation of right expression if not true */\r
-       right_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* push 1 on stack */\r
-       if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 1))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the end of the expression */\r
-       end_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* evaluate right expression */\r
-       A->file->code[right_jump].param[0] = A->file->count;\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* the end of the expression */\r
-       A->file->code[end_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
-/*\r
- * _slang_assemble_select()\r
- *\r
- * select:\r
- *    <condition-expression>\r
- *    jumpz false\r
- *    <true-expression>\r
- *    jump end\r
- * false:\r
- *    <false-expression>\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_select (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint cond_jump, end_jump;\r
-\r
-       /* execute condition expression */\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to false expression if not true */\r
-       cond_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* execute true expression */\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the end of the expression */\r
-       end_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* resolve false point */\r
-       A->file->code[cond_jump].param[0] = A->file->count;\r
-\r
-       /* execute false expression */\r
-       if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the end of the expression */\r
-       A->file->code[end_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
-/*\r
- * _slang_assemble_for()\r
- *\r
- * for:\r
- *    <init-statement>\r
- *    jump start\r
- * break:\r
- *    jump end\r
- * continue:\r
- *    <loop-increment>\r
- * start:\r
- *    <condition-statement>\r
- *    jumpz end\r
- *    <loop-body>\r
- *    jump continue\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_for (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint start_jump, end_jump, cond_jump;\r
-       GLuint break_label, cont_label;\r
-       slang_assembly_flow_control save_flow = A->flow;\r
-\r
-       /* execute initialization statement */\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[0]))\r
-               return GL_FALSE;\r
-\r
-       /* skip the "go to the end of the loop" and loop-increment statements */\r
-       start_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* go to the end of the loop - break statements are directed here */\r
-       break_label = A->file->count;\r
-       end_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the beginning of the loop - continue statements are directed here */\r
-       cont_label = A->file->count;\r
-\r
-       /* execute loop-increment statement */\r
-       if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[2]))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the condition point */\r
-       A->file->code[start_jump].param[0] = A->file->count;\r
-\r
-       /* execute condition statement */\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the end of the loop if not true */\r
-       cond_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* execute loop body */\r
-       A->flow.loop_start = cont_label;\r
-       A->flow.loop_end = break_label;\r
-       if (!_slang_assemble_operation (A, &op->children[3], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[3]))\r
-               return GL_FALSE;\r
-       A->flow = save_flow;\r
-\r
-       /* go to the beginning of the loop */\r
-       if (!slang_assembly_file_push_label (A->file, slang_asm_jump, cont_label))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the end of the loop */\r
-       A->file->code[end_jump].param[0] = A->file->count;\r
-       A->file->code[cond_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
-/*\r
- * _slang_assemble_do()\r
- *\r
- * do:\r
- *    jump start\r
- * break:\r
- *    jump end\r
- * continue:\r
- *    jump condition\r
- * start:\r
- *    <loop-body>\r
- * condition:\r
- *    <condition-statement>\r
- *    jumpz end\r
- *    jump start\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_do (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint skip_jump, end_jump, cont_jump, cond_jump;\r
-       GLuint break_label, cont_label;\r
-       slang_assembly_flow_control save_flow = A->flow;\r
-\r
-       /* skip the "go to the end of the loop" and "go to condition" statements */\r
-       skip_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* go to the end of the loop - break statements are directed here */\r
-       break_label = A->file->count;\r
-       end_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* go to condition - continue statements are directed here */\r
-       cont_label = A->file->count;\r
-       cont_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the beginning of the loop */\r
-       A->file->code[skip_jump].param[0] = A->file->count;\r
-\r
-       /* execute loop body */\r
-       A->flow.loop_start = cont_label;\r
-       A->flow.loop_end = break_label;\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[0]))\r
-               return GL_FALSE;\r
-       A->flow = save_flow;\r
-\r
-       /* resolve condition point */\r
-       A->file->code[cont_jump].param[0] = A->file->count;\r
-\r
-       /* execute condition statement */\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the end of the loop if not true */\r
-       cond_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the beginning of the loop */\r
-       if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the end of the loop */\r
-       A->file->code[end_jump].param[0] = A->file->count;\r
-       A->file->code[cond_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
-/*\r
- * _slang_assemble_while()\r
- *\r
- * while:\r
- *    jump continue\r
- * break:\r
- *    jump end\r
- * continue:\r
- *    <condition-statement>\r
- *    jumpz end\r
- *    <loop-body>\r
- *    jump continue\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_while (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint skip_jump, end_jump, cond_jump;\r
-       GLuint break_label;\r
-       slang_assembly_flow_control save_flow = A->flow;\r
-\r
-       /* skip the "go to the end of the loop" statement */\r
-       skip_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* go to the end of the loop - break statements are directed here */\r
-       break_label = A->file->count;\r
-       end_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the beginning of the loop - continue statements are directed here */\r
-       A->file->code[skip_jump].param[0] = A->file->count;\r
-\r
-       /* execute condition statement */\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to the end of the loop if not true */\r
-       cond_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* execute loop body */\r
-       A->flow.loop_start = A->file->code[skip_jump].param[0];\r
-       A->flow.loop_end = break_label;\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[1]))\r
-               return GL_FALSE;\r
-       A->flow = save_flow;\r
-\r
-       /* jump to the beginning of the loop */\r
-       if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))\r
-               return GL_FALSE;\r
-\r
-       /* resolve the end of the loop */\r
-       A->file->code[end_jump].param[0] = A->file->count;\r
-       A->file->code[cond_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
-/*\r
- * _slang_assemble_if()\r
- *\r
- * if:\r
- *    <condition-statement>\r
- *    jumpz else\r
- *    <true-statement>\r
- *    jump end\r
- * else:\r
- *    <false-statement>\r
- * end:\r
- */\r
-\r
-GLboolean _slang_assemble_if (slang_assemble_ctx *A, slang_operation *op)\r
-{\r
-       GLuint cond_jump, else_jump;\r
-\r
-       /* execute condition statement */\r
-       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))\r
-               return GL_FALSE;\r
-\r
-       /* jump to false-statement if not true */\r
-       cond_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))\r
-               return GL_FALSE;\r
-\r
-       /* execute true-statement */\r
-       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[1]))\r
-               return GL_FALSE;\r
-\r
-       /* skip if-false statement */\r
-       else_jump = A->file->count;\r
-       if (!slang_assembly_file_push (A->file, slang_asm_jump))\r
-               return GL_FALSE;\r
-\r
-       /* resolve start of false-statement */\r
-       A->file->code[cond_jump].param[0] = A->file->count;\r
-\r
-       /* execute false-statement */\r
-       if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))\r
-               return GL_FALSE;\r
-       if (!_slang_cleanup_stack (A, &op->children[2]))\r
-               return GL_FALSE;\r
-\r
-       /* resolve end of if-false statement */\r
-       A->file->code[else_jump].param[0] = A->file->count;\r
-\r
-       return GL_TRUE;\r
-}\r
-\r
+/*
+ * Mesa 3-D graphics library
+ * Version:  6.5
+ *
+ * Copyright (C) 2005-2006  Brian Paul   All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * \file slang_assemble_conditional.c
+ * slang condtional expressions assembler
+ * \author Michal Krol
+ */
+
+#include "imports.h"
+#include "slang_assemble.h"
+#include "slang_compile.h"
+
+/*
+ * _slang_assemble_logicaland()
+ *
+ * and:
+ *    <left-expression>
+ *    jumpz zero
+ *    <right-expression>
+ *    jump end
+ *    zero:
+ *    push 0
+ * end:
+ */
+
+GLboolean _slang_assemble_logicaland (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint zero_jump, end_jump;
+
+       /* evaluate left expression */
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to pushing 0 if not true */
+       zero_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* evaluate right expression */
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to the end of the expression */
+       end_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* push 0 on stack */
+       A->file->code[zero_jump].param[0] = A->file->count;
+       if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 0))
+               return GL_FALSE;
+
+       /* the end of the expression */
+       A->file->code[end_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+
+/*
+ * _slang_assemble_logicalor()
+ *
+ * or:
+ *    <left-expression>
+ *    jumpz right
+ *    push 1
+ *    jump end
+ * right:
+ *    <right-expression>
+ * end:
+ */
+
+GLboolean _slang_assemble_logicalor (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint right_jump, end_jump;
+
+       /* evaluate left expression */
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to evaluation of right expression if not true */
+       right_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* push 1 on stack */
+       if (!slang_assembly_file_push_literal (A->file, slang_asm_bool_push, (GLfloat) 1))
+               return GL_FALSE;
+
+       /* jump to the end of the expression */
+       end_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* evaluate right expression */
+       A->file->code[right_jump].param[0] = A->file->count;
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* the end of the expression */
+       A->file->code[end_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+
+/*
+ * _slang_assemble_select()
+ *
+ * select:
+ *    <condition-expression>
+ *    jumpz false
+ *    <true-expression>
+ *    jump end
+ * false:
+ *    <false-expression>
+ * end:
+ */
+
+GLboolean _slang_assemble_select (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint cond_jump, end_jump;
+
+       /* execute condition expression */
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to false expression if not true */
+       cond_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* execute true expression */
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to the end of the expression */
+       end_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* resolve false point */
+       A->file->code[cond_jump].param[0] = A->file->count;
+
+       /* execute false expression */
+       if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* resolve the end of the expression */
+       A->file->code[end_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+
+/*
+ * _slang_assemble_for()
+ *
+ * for:
+ *    <init-statement>
+ *    jump start
+ * break:
+ *    jump end
+ * continue:
+ *    <loop-increment>
+ * start:
+ *    <condition-statement>
+ *    jumpz end
+ *    <loop-body>
+ *    jump continue
+ * end:
+ */
+
+GLboolean _slang_assemble_for (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint start_jump, end_jump, cond_jump;
+       GLuint break_label, cont_label;
+       slang_assembly_flow_control save_flow = A->flow;
+
+       /* execute initialization statement */
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[0]))
+               return GL_FALSE;
+
+       /* skip the "go to the end of the loop" and loop-increment statements */
+       start_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* go to the end of the loop - break statements are directed here */
+       break_label = A->file->count;
+       end_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* resolve the beginning of the loop - continue statements are directed here */
+       cont_label = A->file->count;
+
+       /* execute loop-increment statement */
+       if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[2]))
+               return GL_FALSE;
+
+       /* resolve the condition point */
+       A->file->code[start_jump].param[0] = A->file->count;
+
+       /* execute condition statement */
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to the end of the loop if not true */
+       cond_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* execute loop body */
+       A->flow.loop_start = cont_label;
+       A->flow.loop_end = break_label;
+       if (!_slang_assemble_operation (A, &op->children[3], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[3]))
+               return GL_FALSE;
+       A->flow = save_flow;
+
+       /* go to the beginning of the loop */
+       if (!slang_assembly_file_push_label (A->file, slang_asm_jump, cont_label))
+               return GL_FALSE;
+
+       /* resolve the end of the loop */
+       A->file->code[end_jump].param[0] = A->file->count;
+       A->file->code[cond_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+
+/*
+ * _slang_assemble_do()
+ *
+ * do:
+ *    jump start
+ * break:
+ *    jump end
+ * continue:
+ *    jump condition
+ * start:
+ *    <loop-body>
+ * condition:
+ *    <condition-statement>
+ *    jumpz end
+ *    jump start
+ * end:
+ */
+
+GLboolean _slang_assemble_do (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint skip_jump, end_jump, cont_jump, cond_jump;
+       GLuint break_label, cont_label;
+       slang_assembly_flow_control save_flow = A->flow;
+
+       /* skip the "go to the end of the loop" and "go to condition" statements */
+       skip_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* go to the end of the loop - break statements are directed here */
+       break_label = A->file->count;
+       end_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* go to condition - continue statements are directed here */
+       cont_label = A->file->count;
+       cont_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* resolve the beginning of the loop */
+       A->file->code[skip_jump].param[0] = A->file->count;
+
+       /* execute loop body */
+       A->flow.loop_start = cont_label;
+       A->flow.loop_end = break_label;
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[0]))
+               return GL_FALSE;
+       A->flow = save_flow;
+
+       /* resolve condition point */
+       A->file->code[cont_jump].param[0] = A->file->count;
+
+       /* execute condition statement */
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to the end of the loop if not true */
+       cond_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* jump to the beginning of the loop */
+       if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))
+               return GL_FALSE;
+
+       /* resolve the end of the loop */
+       A->file->code[end_jump].param[0] = A->file->count;
+       A->file->code[cond_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+
+/*
+ * _slang_assemble_while()
+ *
+ * while:
+ *    jump continue
+ * break:
+ *    jump end
+ * continue:
+ *    <condition-statement>
+ *    jumpz end
+ *    <loop-body>
+ *    jump continue
+ * end:
+ */
+
+GLboolean _slang_assemble_while (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint skip_jump, end_jump, cond_jump;
+       GLuint break_label;
+       slang_assembly_flow_control save_flow = A->flow;
+
+       /* skip the "go to the end of the loop" statement */
+       skip_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* go to the end of the loop - break statements are directed here */
+       break_label = A->file->count;
+       end_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* resolve the beginning of the loop - continue statements are directed here */
+       A->file->code[skip_jump].param[0] = A->file->count;
+
+       /* execute condition statement */
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to the end of the loop if not true */
+       cond_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* execute loop body */
+       A->flow.loop_start = A->file->code[skip_jump].param[0];
+       A->flow.loop_end = break_label;
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[1]))
+               return GL_FALSE;
+       A->flow = save_flow;
+
+       /* jump to the beginning of the loop */
+       if (!slang_assembly_file_push_label (A->file, slang_asm_jump, A->file->code[skip_jump].param[0]))
+               return GL_FALSE;
+
+       /* resolve the end of the loop */
+       A->file->code[end_jump].param[0] = A->file->count;
+       A->file->code[cond_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+
+/*
+ * _slang_assemble_if()
+ *
+ * if:
+ *    <condition-statement>
+ *    jumpz else
+ *    <true-statement>
+ *    jump end
+ * else:
+ *    <false-statement>
+ * end:
+ */
+
+GLboolean _slang_assemble_if (slang_assemble_ctx *A, slang_operation *op)
+{
+       GLuint cond_jump, else_jump;
+
+       /* execute condition statement */
+       if (!_slang_assemble_operation (A, &op->children[0], slang_ref_forbid))
+               return GL_FALSE;
+
+       /* jump to false-statement if not true */
+       cond_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump_if_zero))
+               return GL_FALSE;
+
+       /* execute true-statement */
+       if (!_slang_assemble_operation (A, &op->children[1], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[1]))
+               return GL_FALSE;
+
+       /* skip if-false statement */
+       else_jump = A->file->count;
+       if (!slang_assembly_file_push (A->file, slang_asm_jump))
+               return GL_FALSE;
+
+       /* resolve start of false-statement */
+       A->file->code[cond_jump].param[0] = A->file->count;
+
+       /* execute false-statement */
+       if (!_slang_assemble_operation (A, &op->children[2], slang_ref_forbid/*slang_ref_freelance*/))
+               return GL_FALSE;
+       if (!_slang_cleanup_stack (A, &op->children[2]))
+               return GL_FALSE;
+
+       /* resolve end of if-false statement */
+       A->file->code[else_jump].param[0] = A->file->count;
+
+       return GL_TRUE;
+}
+