From 14c388e3f888166b2c93193dfee93f35e85d1b9b Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Mon, 3 Feb 2014 14:30:02 +0100 Subject: [PATCH] Use %? in the parser rather than stringifying expressions --- codegen/valaccodetransformer.vala | 49 ++++++++++--------------------- vala/valacodebuilder.vala | 8 ++--- vala/valacodetransformer.vala | 10 +++---- vala/valaparser.vala | 35 ++++++++++++++++++++-- 4 files changed, 56 insertions(+), 46 deletions(-) diff --git a/codegen/valaccodetransformer.vala b/codegen/valaccodetransformer.vala index 614efa533..36d6c3d81 100644 --- a/codegen/valaccodetransformer.vala +++ b/codegen/valaccodetransformer.vala @@ -68,10 +68,7 @@ public class Vala.CCodeTransformer : CodeTransformer { if (!always_false (stmt.condition)) { b.open_loop (); if (!always_true (stmt.condition)) { - var cond = expression (@"!$(stmt.condition)"); - b.open_if (cond); - b.add_break (); - b.close (); + statements ("if (!%?) { break; }", {stmt.condition}); } b.add_statement (stmt.body); b.close (); @@ -89,13 +86,7 @@ public class Vala.CCodeTransformer : CodeTransformer { // do not generate variable and if block if condition is always true if (!always_true (stmt.condition)) { var notfirst = b.add_temp_declaration (null, expression ("false")); - b.open_if (expression (notfirst)); - b.open_if (new UnaryExpression (UnaryOperator.LOGICAL_NEGATION, stmt.condition, stmt.source_reference)); - b.add_break (); - b.close (); - b.add_else (); - b.add_assignment (expression (notfirst), expression ("true")); - b.close (); + statements (@"if ($notfirst) { if (!%?) { break; } } else { $notfirst = true; }", {stmt.condition}); } stmt.body.checked = false; b.add_statement (stmt.body); @@ -125,7 +116,7 @@ public class Vala.CCodeTransformer : CodeTransformer { b.close (); if (stmt.condition != null && !always_true (stmt.condition)) { - statements (@"if (!$(stmt.condition)) break;"); + statements ("if (!%?) break;", {stmt.condition}); } b.add_statement (stmt.body); @@ -255,11 +246,7 @@ public class Vala.CCodeTransformer : CodeTransformer { begin_replace_expression (expr); var result = b.add_temp_declaration (expr.value_type); - statements (@"if ($(expr.condition)) { - $result = $(expr.true_expression); - } else { - $result = $(expr.false_expression); - }"); + statements (@"if (%?) { $result = %?; } else { $result = %?; }", {expr.condition, expr.true_expression, expr.false_expression}); replacement = return_temp_access (result, expr.value_type, target_type, formal_target_type); end_replace_expression (replacement); @@ -280,26 +267,18 @@ public class Vala.CCodeTransformer : CodeTransformer { && (expr.operator == BinaryOperator.AND || expr.operator == BinaryOperator.OR)) { var is_and = expr.operator == BinaryOperator.AND; var result = b.add_temp_declaration (data_type ("bool")); - b.open_if (expr.left); - if (is_and) { - b.add_assignment (expression (result), expr.right); - } else { - b.add_expression (expression (@"$result = true")); - } - b.add_else (); + if (is_and) { - b.add_expression (expression (@"$result = false")); + statements (@"if (%?) { $result = %?; } else { $result = false; }", {expr.left, expr.right}); } else { - b.add_assignment (expression (result), expr.right); + statements (@"if (%?) { $result = true; } else { $result = %?; }", {expr.left, expr.right}); } - b.close (); + replacement = expression (result); } else if (expr.operator == BinaryOperator.COALESCE) { var result = b.add_temp_declaration (copy_type (expr.value_type, null, true), expr.left); - b.open_if (expression (@"$result == null")); - b.add_assignment (expression (result), expr.right); - b.close (); + statements (@"if ($result == null) { $result = %?; }", {expr.right}); replacement = return_temp_access (result, expr.value_type, target_type); } else if (expr.operator == BinaryOperator.IN && !(expr.left.value_type.compatible (context.analyzer.int_type) && expr.right.value_type.compatible (context.analyzer.int_type)) && !(expr.right.value_type is ArrayType)) { @@ -378,7 +357,7 @@ public class Vala.CCodeTransformer : CodeTransformer { } else { replacement = stringify (expression_list[0]); if (expression_list.size > 1) { - var concat = (MethodCall) expression (@"$replacement.concat()"); + var concat = (MethodCall) expression ("%?.concat ()", {replacement}); for (int i = 1; i < expression_list.size; i++) { concat.add_argument (stringify (expression_list[i])); } @@ -394,9 +373,11 @@ public class Vala.CCodeTransformer : CodeTransformer { begin_replace_expression (expr); var result = b.add_temp_declaration (copy_type (expr.value_type), expr.inner); - var op = expr.increment ? "+ 1" : "- 1"; - b.add_expression (expression (@"$(expr.inner) = $result $op")); - + if (expr.increment) { + statements (@"$(expr.inner) = $result + 1;"); + } else { + statements (@"$(expr.inner) = $result - 1;"); + } var replacement = return_temp_access (result, expr.value_type, expr.target_type); end_replace_expression (replacement); diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala index 24774e71e..90d3c81d7 100644 --- a/vala/valacodebuilder.vala +++ b/vala/valacodebuilder.vala @@ -267,12 +267,12 @@ public class Vala.CodeBuilder { /* Utilities for building the code */ - public Expression expression (string str) { - return new Parser().parse_expression_string (str, source_reference); + public Expression expression (string str, owned Expression[]? replacements = null) { + return new Parser().parse_expression_string (str, (owned) replacements, source_reference); } - public void statements (string str) { - new Parser().parse_statements_string (str, current_block, source_reference); + public void statements (string str, owned Expression[]? replacements = null) { + new Parser().parse_statements_string (str, current_block, (owned) replacements, source_reference); } // only qualified types, will slightly simplify the work of SymbolResolver diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala index a22842c68..ef811eb42 100644 --- a/vala/valacodetransformer.vala +++ b/vala/valacodetransformer.vala @@ -185,12 +185,12 @@ public class Vala.CodeTransformer : CodeVisitor { return CodeBuilder.data_type (s, value_owned, nullable); } - public Expression expression (string str) { - return b.expression (str); + public Expression expression (string str, owned Expression[]? replacements = null) { + return b.expression (str, (owned) replacements); } - public void statements (string str) { - b.statements (str); + public void statements (string str, owned Expression[]? replacements = null) { + b.statements (str, (owned) replacements); } public void check (CodeNode node) { @@ -233,7 +233,7 @@ public class Vala.CodeTransformer : CodeVisitor { if (expr.value_type != null && expr.value_type.data_type != null && expr.value_type.data_type.is_subtype_of (context.analyzer.string_type.data_type)) { return expr; } else { - return expression (@"$expr.to_string ()"); + return expression (@"%?.to_string ()", {expr}); } } diff --git a/vala/valaparser.vala b/vala/valaparser.vala index ee1907d36..93eeeec5e 100644 --- a/vala/valaparser.vala +++ b/vala/valaparser.vala @@ -31,6 +31,8 @@ public class Vala.Parser : CodeVisitor { CodeContext context; bool compiler_code = false; SourceReference? from_string_reference = null; + Expression[]? replacements = null; + int replacement_index = 0; // token buffer TokenInfo[] tokens; @@ -340,12 +342,14 @@ public class Vala.Parser : CodeVisitor { } } - public Expression? parse_expression_string (string str, SourceReference source_reference) { + public Expression? parse_expression_string (string str, owned Expression[]? replacements, SourceReference source_reference) { Expression? result = null; compiler_code = true; context = source_reference.file.context; from_string_reference = source_reference; + this.replacements = (owned) replacements; + replacement_index = 0; scanner = new Scanner.from_string (str, source_reference.file); index = -1; @@ -359,17 +363,25 @@ public class Vala.Parser : CodeVisitor { Report.error (source_reference, "internal error: %s".printf (e.message)); } + if (replacements.length > 0 && ++replacement_index != replacements.length) { + Report.error (source_reference, "internal error: %i replacements for %i placeholders".printf (replacements.length, replacement_index)); + } + scanner = null; + replacement_index = 0; + this.replacements = null; from_string_reference = null; compiler_code = false; return result; } - public void parse_statements_string (string str, Block block, SourceReference source_reference) { + public void parse_statements_string (string str, Block block, owned Expression[]? replacements, SourceReference source_reference) { compiler_code = true; context = source_reference.file.context; from_string_reference = source_reference; + this.replacements = (owned) replacements; + replacement_index = 0; scanner = new Scanner.from_string (str, source_reference.file); index = -1; @@ -383,7 +395,13 @@ public class Vala.Parser : CodeVisitor { Report.error (source_reference, "internal error: %s".printf (e.message)); } + if (replacements.length > 0 && ++replacement_index != replacements.length) { + Report.error (source_reference, "internal error: %i replacements for %i placeholders".printf (replacements.length, replacement_index)); + } + scanner = null; + replacement_index = 0; + this.replacements = null; from_string_reference = null; compiler_code = false; } @@ -714,7 +732,18 @@ public class Vala.Parser : CodeVisitor { expr = parse_typeof_expression (); break; default: - expr = parse_simple_name (); + if (compiler_code && current () == TokenType.PERCENT) { + var inner_begin = get_location (); + next (); + if (accept (TokenType.INTERR)) { + expr = (owned) replacements[replacement_index++]; + } else { + rollback (inner_begin); + expr = parse_simple_name (); + } + } else { + expr = parse_simple_name (); + } break; } -- 2.47.2