[vala/wip/transform: 30/50] Complete the gvariant transformer
- From: Luca Bruno <lucabru src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [vala/wip/transform: 30/50] Complete the gvariant transformer
- Date: Fri, 13 Apr 2012 13:09:46 +0000 (UTC)
commit bfc83af234e91216fce10cad3305b4a84fb776ed
Author: Luca Bruno <lucabru src gnome org>
Date: Tue Jan 3 15:34:48 2012 +0100
Complete the gvariant transformer
codegen/valagvariantmodule.vala | 110 ----------------------------------
codegen/valagvarianttransformer.vala | 98 +++++++++++++++++++++++++-----
vala/valacodebuilder.vala | 62 +++++++++++++++++++
vala/valacodetransformer.vala | 7 ++-
4 files changed, 149 insertions(+), 128 deletions(-)
---
diff --git a/codegen/valagvariantmodule.vala b/codegen/valagvariantmodule.vala
index 8b08731..3684fa9 100644
--- a/codegen/valagvariantmodule.vala
+++ b/codegen/valagvariantmodule.vala
@@ -142,29 +142,6 @@ public class Vala.GVariantModule : GAsyncModule {
}
}
- public override void visit_enum (Enum en) {
- base.visit_enum (en);
-
- if (is_string_marshalled_enum (en)) {
- // strcmp
- cfile.add_include ("string.h");
-
- cfile.add_function (generate_enum_from_string_function (en));
- cfile.add_function (generate_enum_to_string_function (en));
- }
- }
-
- public override bool generate_enum_declaration (Enum en, CCodeFile decl_space) {
- if (base.generate_enum_declaration (en, decl_space)) {
- if (is_string_marshalled_enum (en)) {
- decl_space.add_function_declaration (generate_enum_from_string_function_declaration (en));
- decl_space.add_function_declaration (generate_enum_to_string_function_declaration (en));
- }
- return true;
- }
- return false;
- }
-
CCodeExpression? get_array_length (CCodeExpression expr, int dim) {
var id = expr as CCodeIdentifier;
var ma = expr as CCodeMemberAccess;
@@ -195,58 +172,6 @@ public class Vala.GVariantModule : GAsyncModule {
return from_string_call;
}
- public CCodeFunction generate_enum_from_string_function_declaration (Enum en) {
- var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
-
- var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en));
- from_string_func.add_parameter (new CCodeParameter ("str", "const char*"));
- from_string_func.add_parameter (new CCodeParameter ("error", "GError**"));
-
- return from_string_func;
- }
-
- public CCodeFunction generate_enum_from_string_function (Enum en) {
- var from_string_name = "%s_from_string".printf (get_ccode_lower_case_name (en, null));
-
- var from_string_func = new CCodeFunction (from_string_name, get_ccode_name (en));
- from_string_func.add_parameter (new CCodeParameter ("str", "const char*"));
- from_string_func.add_parameter (new CCodeParameter ("error", "GError**"));
-
- push_function (from_string_func);
-
- ccode.add_declaration (get_ccode_name (en), new CCodeVariableDeclarator.zero ("value", new CCodeConstant ("0")));
-
- bool firstif = true;
- foreach (EnumValue enum_value in en.get_values ()) {
- string dbus_value = get_dbus_value (enum_value, enum_value.name);
- var string_comparison = new CCodeFunctionCall (new CCodeIdentifier ("strcmp"));
- string_comparison.add_argument (new CCodeIdentifier ("str"));
- string_comparison.add_argument (new CCodeConstant ("\"%s\"".printf (dbus_value)));
- var cond = new CCodeBinaryExpression (CCodeBinaryOperator.EQUALITY, string_comparison, new CCodeConstant ("0"));
- if (firstif) {
- ccode.open_if (cond);
- firstif = false;
- } else {
- ccode.else_if (cond);
- }
- ccode.add_assignment (new CCodeIdentifier ("value"), new CCodeIdentifier (get_ccode_name (enum_value)));
- }
-
- ccode.add_else ();
- var set_error = new CCodeFunctionCall (new CCodeIdentifier ("g_set_error"));
- set_error.add_argument (new CCodeIdentifier ("error"));
- set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR"));
- set_error.add_argument (new CCodeIdentifier ("G_DBUS_ERROR_INVALID_ARGS"));
- set_error.add_argument (new CCodeConstant ("\"Invalid value for enum `%s'\"".printf (get_ccode_name (en))));
- ccode.add_expression (set_error);
- ccode.close ();
-
- ccode.add_return (new CCodeIdentifier ("value"));
-
- pop_function ();
- return from_string_func;
- }
-
CCodeExpression deserialize_basic (BasicTypeInfo basic_type, CCodeExpression variant_expr, bool transfer = false) {
var get_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_get_" + basic_type.type_name));
get_call.add_argument (variant_expr);
@@ -523,41 +448,6 @@ public class Vala.GVariantModule : GAsyncModule {
return to_string_call;
}
- public CCodeFunction generate_enum_to_string_function_declaration (Enum en) {
- var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
-
- var to_string_func = new CCodeFunction (to_string_name, "const char*");
- to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
-
- return to_string_func;
- }
-
- public CCodeFunction generate_enum_to_string_function (Enum en) {
- var to_string_name = "%s_to_string".printf (get_ccode_lower_case_name (en, null));
-
- var to_string_func = new CCodeFunction (to_string_name, "const char*");
- to_string_func.add_parameter (new CCodeParameter ("value", get_ccode_name (en)));
-
- push_function (to_string_func);
-
- ccode.add_declaration ("const char *", new CCodeVariableDeclarator ("str"));
-
- ccode.open_switch (new CCodeIdentifier ("value"));
- foreach (EnumValue enum_value in en.get_values ()) {
- string dbus_value = get_dbus_value (enum_value, enum_value.name);
- ccode.add_case (new CCodeIdentifier (get_ccode_name (enum_value)));
- ccode.add_assignment (new CCodeIdentifier ("str"), new CCodeConstant ("\"%s\"".printf (dbus_value)));
- ccode.add_break ();
- }
-
- ccode.close();
-
- ccode.add_return (new CCodeIdentifier ("str"));
-
- pop_function ();
- return to_string_func;
- }
-
CCodeExpression? serialize_basic (BasicTypeInfo basic_type, CCodeExpression expr) {
var new_call = new CCodeFunctionCall (new CCodeIdentifier ("g_variant_new_" + basic_type.type_name));
new_call.add_argument (expr);
diff --git a/codegen/valagvarianttransformer.vala b/codegen/valagvarianttransformer.vala
index 170595f..686c8f8 100644
--- a/codegen/valagvarianttransformer.vala
+++ b/codegen/valagvarianttransformer.vala
@@ -45,6 +45,13 @@ public class Vala.GVariantTransformer : CodeTransformer {
{ "g", "signature", true }
};
+ static bool is_string_marshalled_enum (TypeSymbol? symbol) {
+ if (symbol != null && symbol is Enum) {
+ return symbol.get_attribute_bool ("DBus", "use_string_marshalling");
+ }
+ return false;
+ }
+
bool get_basic_type_info (string signature, out BasicTypeInfo basic_type) {
foreach (BasicTypeInfo info in basic_types) {
if (info.signature == signature) {
@@ -56,10 +63,6 @@ public class Vala.GVariantTransformer : CodeTransformer {
return false;
}
- Expression expression (string str) {
- return new Parser().parse_expression_string (str, b.source_reference);
- }
-
Expression serialize_basic (BasicTypeInfo basic_type, Expression expr) {
var new_call = (ObjectCreationExpression) expression (@"new GLib.Variant.$(basic_type.type_name)()");
new_call.add_argument (expr);
@@ -70,13 +73,6 @@ public class Vala.GVariantTransformer : CodeTransformer {
return symbol.get_attribute_string ("DBus", "signature");
}
- static bool is_string_marshalled_enum (TypeSymbol? symbol) {
- if (symbol != null && symbol is Enum) {
- return symbol.get_attribute_bool ("DBus", "use_string_marshalling");
- }
- return false;
- }
-
public static string? get_type_signature (DataType datatype, Symbol? symbol = null) {
if (symbol != null) {
string sig = get_dbus_signature (symbol);
@@ -400,10 +396,70 @@ public class Vala.GVariantTransformer : CodeTransformer {
return call;
}
- public override void visit_cast_expression (CastExpression expr) {
- base.visit_cast_expression (expr);
+ string get_dbus_value (EnumValue value, string default_value) {
+ var dbus_value = value.get_attribute_string ("DBus", "value");
+ if (dbus_value != null) {
+ return dbus_value;;
+ }
+ return default_value;
+ }
+ void add_enum_from_string_method (Enum en) {
+ if (en.scope.lookup ("from_string") != null) {
+ return;
+ }
+ var m = new Method ("from_string", context.analyzer.get_data_type_for_symbol (en), en.source_reference);
+ m.add_error_type (data_type ("GLib.DBusError.INVALID_ARGS"));
+ m.add_parameter (new Parameter ("str", data_type ("string", false), en.source_reference));
+ en.add_method (m);
+ m.binding = MemberBinding.STATIC;
+ m.access = SymbolAccessibility.PUBLIC;
+ b = new CodeBuilder.for_method (m);
+
+ b.open_switch (expression ("str"), null);
+ b.add_throw (expression ("new GLib.DBusError.INVALID_ARGS (\"Invalid value for enum `%s'\")".printf (CCodeBaseModule.get_ccode_name (en))));
+ foreach (var enum_value in en.get_values ()) {
+ string dbus_value = get_dbus_value (enum_value, enum_value.name);
+ b.add_section (expression (@"\"$dbus_value\""));
+ b.add_return (expression (@"$(en.get_full_name()).$(enum_value.name)"));
+ }
+ b.close ();
+
+ check (m);
+ }
+
+ void add_enum_to_string_method (Enum en) {
+ if (en.scope.lookup ("to_string") != null) {
+ return;
+ }
+ var m = new Method ("to_string", data_type ("string", false, true), en.source_reference);
+ en.add_method (m);
+ m.access = SymbolAccessibility.PUBLIC;
+ b = new CodeBuilder.for_method (m);
+
+ b.open_switch (expression ("this"), null);
+ b.add_return (expression ("null"));
+ foreach (var enum_value in en.get_values ()) {
+ string dbus_value = get_dbus_value (enum_value, enum_value.name);
+ b.add_section (expression (@"$(en.get_full_name()).$(enum_value.name)"));
+ b.add_return (expression (@"\"$dbus_value\""));
+ }
+ b.close ();
+
+ check (m);
+ }
+
+ public override void visit_enum (Enum en) {
+ if (!en.external && is_string_marshalled_enum (en) && context.has_package ("gio-2.0")) {
+ add_enum_from_string_method (en);
+ add_enum_to_string_method (en);
+ }
+ base.visit_enum (en);
+ }
+
+ public override void visit_cast_expression (CastExpression expr) {
if (!(expr.inner.value_type.data_type == context.analyzer.gvariant_type.data_type && expr.type_reference.data_type != context.analyzer.gvariant_type.data_type)) {
+ base.visit_cast_expression (expr);
return;
}
@@ -414,7 +470,13 @@ public class Vala.GVariantTransformer : CodeTransformer {
BasicTypeInfo basic_type;
Expression result = null;
- if (get_basic_type_info (get_type_signature (type), out basic_type)) {
+ if (is_string_marshalled_enum (type.data_type)) {
+ get_basic_type_info ("s", out basic_type);
+ result = deserialize_basic (basic_type, expr.inner);
+ var call = (MethodCall) expression (@"$(type.data_type.get_full_name()).from_string ()");
+ call.add_argument (result);
+ result = call;
+ } else if (get_basic_type_info (get_type_signature (type), out basic_type)) {
result = deserialize_basic (basic_type, expr.inner);
} else if (type is ArrayType) {
result = deserialize_array ((ArrayType) type, expr.inner);
@@ -436,10 +498,9 @@ public class Vala.GVariantTransformer : CodeTransformer {
}
public override void visit_expression (Expression expr) {
- base.visit_expression (expr);
-
if (!(context.profile == Profile.GOBJECT && expr.target_type != null && expr.target_type.data_type == context.analyzer.gvariant_type.data_type && !(expr.value_type is NullType) && expr.value_type.data_type != context.analyzer.gvariant_type.data_type)) {
// no implicit gvariant boxing
+ base.visit_expression (expr);
return;
}
@@ -450,7 +511,10 @@ public class Vala.GVariantTransformer : CodeTransformer {
BasicTypeInfo basic_type;
Expression result = null;
- if (get_basic_type_info (get_type_signature (type), out basic_type)) {
+ if (is_string_marshalled_enum (type.data_type)) {
+ get_basic_type_info ("s", out basic_type);
+ result = new MethodCall (new MemberAccess (expr, "to_string"), b.source_reference);
+ } else if (get_basic_type_info (get_type_signature (type), out basic_type)) {
result = serialize_basic (basic_type, expr);
} else if (type is ArrayType) {
result = serialize_array ((ArrayType) type, expr);
diff --git a/vala/valacodebuilder.vala b/vala/valacodebuilder.vala
index b981bf2..ec7d370 100644
--- a/vala/valacodebuilder.vala
+++ b/vala/valacodebuilder.vala
@@ -48,6 +48,14 @@ public class Vala.CodeBuilder {
build_context.check_nodes.add (build_context.current_block);
}
+ public CodeBuilder.for_method (Method m) {
+ source_reference = m.source_reference;
+ build_context = new BuildContext ();
+ build_context.insert_block = m.body = new Block (source_reference);
+ build_context.insert_statement = build_context.current_block = new Block (source_reference);
+ m.body.add_statement (build_context.current_block);
+ }
+
public void check (CodeTransformer transformer) {
foreach (var node in build_context.check_nodes) {
transformer.check (node);
@@ -138,6 +146,56 @@ public class Vala.CodeBuilder {
parent_block.add_statement (stmt);
}
+ public void open_switch (Expression expression, Expression? first_label) {
+ var parent_block = build_context.current_block;
+
+ var stmt = new SwitchStatement (expression, source_reference);
+ build_context.statement_stack.add (stmt);
+
+ var section = new SwitchSection (source_reference);
+ SwitchLabel label;
+ if (first_label == null) {
+ label = new SwitchLabel.with_default (source_reference);
+ } else {
+ label = new SwitchLabel (first_label);
+ }
+ section.add_label (label);
+ build_context.current_block = section;
+ build_context.statement_stack.add (section);
+
+ parent_block.add_statement (stmt);
+ stmt.add_section (section);
+ }
+
+ public void add_section (Expression? expression) {
+ build_context.statement_stack.remove_at (build_context.statement_stack.size - 1);
+
+ var stmt = (SwitchStatement) build_context.statement_stack[build_context.statement_stack.size - 1];
+ var section = new SwitchSection (source_reference);
+ SwitchLabel label;
+ if (expression == null) {
+ label = new SwitchLabel.with_default (source_reference);
+ } else {
+ label = new SwitchLabel (expression);
+ }
+ section.add_label (label);
+ build_context.current_block = section;
+ build_context.statement_stack.add (section);
+
+ stmt.add_section (section);
+ }
+
+ public void add_label (Expression? expression) {
+ var section = (SwitchSection) build_context.statement_stack[build_context.statement_stack.size - 1];
+ SwitchLabel label;
+ if (expression == null) {
+ label = new SwitchLabel.with_default (source_reference);
+ } else {
+ label = new SwitchLabel (expression);
+ }
+ section.add_label (label);
+ }
+
public void add_statement (Statement statement) {
build_context.current_block.add_statement (statement);
}
@@ -150,6 +208,10 @@ public class Vala.CodeBuilder {
add_expression (new Assignment (left, right, AssignmentOperator.SIMPLE, source_reference));
}
+ public void add_throw (Expression expression) {
+ add_statement (new ThrowStatement (expression, source_reference));
+ }
+
public void add_return (Expression? expression = null) {
add_statement (new ReturnStatement (expression, source_reference));
}
diff --git a/vala/valacodetransformer.vala b/vala/valacodetransformer.vala
index fcca37b..f79edca 100644
--- a/vala/valacodetransformer.vala
+++ b/vala/valacodetransformer.vala
@@ -86,12 +86,17 @@ public class Vala.CodeTransformer : CodeVisitor {
}
// only qualified types, will slightly simplify the work of SymbolResolver
- public DataType data_type (string s, bool value_owned = true) {
+ public DataType data_type (string s, bool value_owned = true, bool nullable = false) {
DataType type = context.analyzer.get_data_type_for_symbol ((TypeSymbol) symbol_from_string (s));
type.value_owned = value_owned;
+ type.nullable = nullable;
return type;
}
+ public Expression expression (string str) {
+ return new Parser().parse_expression_string (str, b.source_reference);
+ }
+
public void check (CodeNode node) {
node.accept (context.resolver);
if (!node.check (context)) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]