[vala/wip/issue/327: 19/27] Added with statement declaration
- From: Rico Tzschichholz <ricotz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/issue/327: 19/27] Added with statement declaration
- Date: Thu, 23 Apr 2020 17:39:29 +0000 (UTC)
commit df805d099c6b30fb96b2d5a5df289a2d7503c2d5
Author: Nick Schrader <nick schrader mailbox org>
Date: Sun Apr 5 20:32:01 2020 -0300
Added with statement declaration
vala/valaparser.vala | 44 +++++++++++++++++++---
vala/valawithstatement.vala | 90 +++++++++++++++++++++++++++++++++------------
2 files changed, 105 insertions(+), 29 deletions(-)
---
diff --git a/vala/valaparser.vala b/vala/valaparser.vala
index f2d0e9cbe..5da12abe3 100644
--- a/vala/valaparser.vala
+++ b/vala/valaparser.vala
@@ -2264,15 +2264,47 @@ public class Vala.Parser : CodeVisitor {
return new DeleteStatement (expr, src);
}
- Statement parse_with_statement () throws ParseError {
+ inline void expect_or_throw (TokenType type) throws ParseError {
+ // Don't continue on any minor issue as the with-syntax is a fragile left recursion
+ if (!accept (type)) {
+ throw new ParseError.SYNTAX(@"expected $(type.to_string ())");
+ }
+ }
+
+ Statement? parse_with_statement () throws ParseError {
var begin = get_location ();
- expect (TokenType.WITH);
- expect (TokenType.OPEN_PARENS);
- var expr = parse_expression ();
- expect (TokenType.CLOSE_PARENS);
+ expect_or_throw (TokenType.WITH);
+ expect_or_throw (TokenType.OPEN_PARENS);
+ var expr_or_decl = get_location();
+
+ DataType? variable_type = null;
+ string? variable_name = null;
+
+ // Try "with (expr)"
+ Expression expr = parse_expression ();
+ if (!accept (TokenType.CLOSE_PARENS)) {
+ // Try "with (var identifier = expr)"
+ rollback (expr_or_decl);
+ if (accept (TokenType.VAR)) {
+ variable_name = parse_identifier ();
+ expect_or_throw (TokenType.ASSIGN);
+ } else {
+ // Try "with (type identifier = expr)"
+ variable_type = parse_type (true, true);
+ variable_name = parse_identifier ();
+ if (!accept (TokenType.ASSIGN)) {
+ // Fallback to "with (expr)"
+ rollback (expr_or_decl);
+ }
+ }
+
+ expr = parse_expression ();
+ expect_or_throw (TokenType.CLOSE_PARENS);
+ }
+
var src = get_src (begin);
var body = parse_embedded_statement ("with", false);
- return new WithStatement (expr, body, src);
+ return new WithStatement (variable_type, variable_name, expr, body, src);
}
string parse_attribute_value () throws ParseError {
diff --git a/vala/valawithstatement.vala b/vala/valawithstatement.vala
index 43bd91d71..06dc12f51 100644
--- a/vala/valawithstatement.vala
+++ b/vala/valawithstatement.vala
@@ -36,6 +36,24 @@ public class Vala.WithStatement : Block {
}
}
+ /**
+ * Specifies the with-variable type.
+ */
+ public DataType? type_reference {
+ get { return _data_type; }
+ private set {
+ _data_type = value;
+ if (_data_type != null) {
+ _data_type.parent_node = this;
+ }
+ }
+ }
+
+ /**
+ * Specifies the with-variable name.
+ */
+ public string? with_variable_name { get; private set; }
+
/**
* Specifies the with-variable.
*/
@@ -56,11 +74,15 @@ public class Vala.WithStatement : Block {
private Expression _expression;
private Block _body;
+ private DataType? _data_type;
- public WithStatement (Expression expression, Block body, SourceReference? source_reference = null) {
+ public WithStatement (DataType? type_reference, string? variable_name, Expression expression,
+ Block body, SourceReference? source_reference = null) {
base (source_reference);
this.expression = expression;
this.body = body;
+ this.type_reference = type_reference;
+ this.with_variable_name = variable_name;
}
public override void accept (CodeVisitor visitor) {
@@ -71,6 +93,11 @@ public class Vala.WithStatement : Block {
if (expression.symbol_reference == with_variable) {
expression.accept (visitor);
}
+
+ if (type_reference != null) {
+ type_reference.accept (visitor);
+ }
+
if (body != null) {
body.accept (visitor);
}
@@ -82,6 +109,12 @@ public class Vala.WithStatement : Block {
}
}
+ public override void replace_type (DataType old_type, DataType new_type) {
+ if (type_reference == old_type) {
+ type_reference = new_type;
+ }
+ }
+
bool is_object_or_value_type (DataType? type) {
if (type == null) {
return false;
@@ -93,13 +126,30 @@ public class Vala.WithStatement : Block {
}
}
- LocalVariable insert_local_variable_if_necessary () {
- LocalVariable local_var = expression.symbol_reference as LocalVariable;
- if (local_var == null) {
- local_var = new LocalVariable (expression.value_type, "_with_local%d_".printf
(next_with_id++), expression, source_reference);
+ void insert_local_variable_if_necessary () {
+ var local_var = expression.symbol_reference as LocalVariable;
+ if (with_variable_name != null || local_var == null) {
+ var n = with_variable_name ?? "_with_local%d_".printf (next_with_id++);
+ local_var = new LocalVariable (type_reference, n, expression, source_reference);
body.insert_statement (0, new DeclarationStatement (local_var, source_reference));
}
- return local_var;
+ with_variable = local_var;
+ }
+
+ void change_scope_and_check_body (CodeContext context) {
+ var old_symbol = context.analyzer.current_symbol;
+ owner = context.analyzer.current_symbol.scope;
+ context.analyzer.current_symbol = this;
+ body.check (context);
+ context.analyzer.current_symbol = old_symbol;
+ }
+
+ bool is_type_reference_compatible () {
+ if (type_reference == null) {
+ type_reference = expression.value_type.copy();
+ }
+
+ return expression.value_type.compatible(type_reference);
}
public override bool check (CodeContext context) {
@@ -108,25 +158,19 @@ public class Vala.WithStatement : Block {
}
checked = true;
-
- expression.check (context);
-
- if (!is_object_or_value_type (expression.value_type)) {
- error = true;
- Report.error (expression.source_reference, "Expression must be of an object or basic
type");
- return false;
+ if (expression.check (context)) {
+ if (!is_object_or_value_type (expression.value_type)) {
+ error = true;
+ Report.error (expression.source_reference, "With: Expression must be of an
object or basic type");
+ } else if (!is_type_reference_compatible ()) {
+ error = true;
+ Report.error (type_reference.source_reference, @"With: Cannot convert from
`$(expression.value_type)' to `$(type_reference)'");
+ } else {
+ insert_local_variable_if_necessary ();
+ change_scope_and_check_body (context);
+ }
}
- with_variable = insert_local_variable_if_necessary ();
-
- var old_symbol = context.analyzer.current_symbol;
- owner = context.analyzer.current_symbol.scope;
- context.analyzer.current_symbol = this;
-
- body.check (context);
-
- context.analyzer.current_symbol = old_symbol;
-
return !error;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]