+ /* return assignments */
+ if (parser->tok == '=') {
+ if (!OPTS_FLAG(RETURN_ASSIGNMENTS)) {
+ parseerror(parser, "return assignments not activated, try using -freturn-assigments");
+ return false;
+ }
+
+ if (type_store_instr[expected->expression.next->vtype] == VINSTR_END) {
+ char ty1[1024];
+ ast_type_to_string(expected->expression.next, ty1, sizeof(ty1));
+ parseerror(parser, "invalid return type: `%s'", ty1);
+ return false;
+ }
+
+ if (!parser_next(parser)) {
+ parseerror(parser, "expected return assignment expression");
+ return false;
+ }
+
+ if (!(exp = parse_expression_leave(parser, false, false, false)))
+ return false;
+
+ /* prepare the return value */
+ if (!retval) {
+ retval = ast_value_new(ctx, "#LOCAL_RETURN", TYPE_VOID);
+ ast_type_adopt(retval, expected->expression.next);
+ parser->function->return_value = retval;
+ }
+
+ if (!ast_compare_type(exp, (ast_expression*)retval)) {
+ char ty1[1024], ty2[1024];
+ ast_type_to_string(exp, ty1, sizeof(ty1));
+ ast_type_to_string(&retval->expression, ty2, sizeof(ty2));
+ parseerror(parser, "invalid type for return value: `%s', expected `%s'", ty1, ty2);
+ }
+
+ /* store to 'return' local variable */
+ var = (ast_expression*)ast_store_new(
+ ctx,
+ type_store_instr[expected->expression.next->vtype],
+ (ast_expression*)retval, exp);
+
+ if (!var) {
+ ast_unref(exp);
+ return false;
+ }
+
+ if (parser->tok != ';')
+ parseerror(parser, "missing semicolon after return assignment");
+ else if (!parser_next(parser))
+ parseerror(parser, "parse error after return assignment");
+
+ *out = var;
+ return true;
+ }
+