From 4b1c87bdedac8fcf63f61c99db16f274ab658e10 Mon Sep 17 00:00:00 2001 From: Jamie McCracken Date: Mon, 16 Jun 2008 04:28:31 +0000 Subject: [PATCH] added built in list and dict (HashMap) support with automatic type 2008-06-16 Jamie McCracken * vala/valagenieparser.vala: * vala/valageniescanner.vala: * vala/valagenietokentype.vala: added built in list and dict (HashMap) support with automatic type dependent hash and equal functions svn path=/trunk/; revision=1597 --- ChangeLog | 8 +++ vala/valagenieparser.vala | 131 +++++++++++++++++++++++++++++++++++++++---- vala/valageniescanner.vala | 13 ++++- vala/valagenietokentype.vala | 4 ++ 4 files changed, 143 insertions(+), 13 deletions(-) diff --git a/ChangeLog b/ChangeLog index 84f365b..41781a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-06-16 Jamie McCracken + + * vala/valagenieparser.vala: + * vala/valageniescanner.vala: + * vala/valagenietokentype.vala: + + added built in list and dict (HashMap) support with automatic type dependent hash and equal functions + 2008-06-16 Jürg Billeter * gobject/valaccodegenerator.vala: diff --git a/vala/valagenieparser.vala b/vala/valagenieparser.vala index 2dd4169..12b11ec 100644 --- a/vala/valagenieparser.vala +++ b/vala/valagenieparser.vala @@ -43,6 +43,9 @@ public class Vala.Genie.Parser : CodeVisitor { string comment; string class_name; + + /* we need to know whether to automatically add these using directives */ + bool has_uses_glib; /* hack needed to know if any part of an expression is a lambda one */ bool current_expr_is_lambda; @@ -69,6 +72,7 @@ public class Vala.Genie.Parser : CodeVisitor { construct { tokens = new TokenInfo[BUFFER_SIZE]; + has_uses_glib = false; class_name = null; current_expr_is_lambda = false; } @@ -396,7 +400,7 @@ public class Vala.Genie.Parser : CodeVisitor { accept (TokenType.WEAK); - if (accept (TokenType.ARRAY)) { + if (accept (TokenType.ARRAY) || accept (TokenType.LIST) || accept (TokenType.DICT)) { accept (TokenType.OF); } @@ -426,6 +430,9 @@ public class Vala.Genie.Parser : CodeVisitor { return type; } + Gee.List type_arg_list = null; + UnresolvedSymbol sym = null; + bool is_dynamic = accept (TokenType.DYNAMIC); bool value_owned = owned_by_default; if (owned_by_default) { @@ -439,9 +446,36 @@ public class Vala.Genie.Parser : CodeVisitor { expect (TokenType.OF); is_array = true; } - - var sym = parse_symbol_name (); - Gee.List type_arg_list = parse_type_argument_list (false); + + /* handle lists */ + bool is_list = false; + + if (accept (TokenType.LIST)) { + expect (TokenType.OF); + prev (); + is_list = true; + } + + /* handle dicts */ + bool is_dict = false; + + if (accept (TokenType.DICT)) { + expect (TokenType.OF); + prev (); + is_dict = true; + } + + if (is_list) { + var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin)); + sym = new UnresolvedSymbol (sym_parent, "ArrayList", get_src (begin)); + } else if (is_dict) { + var sym_parent = new UnresolvedSymbol (null, "Gee", get_src (begin)); + sym = new UnresolvedSymbol (sym_parent, "HashMap", get_src (begin)); + } else { + sym = parse_symbol_name (); + } + + type_arg_list = parse_type_argument_list (false); DataType type = new UnresolvedType.from_symbol (sym, get_src (begin)); if (type_arg_list != null) { @@ -815,6 +849,23 @@ public class Vala.Genie.Parser : CodeVisitor { return expr; } + if (accept (TokenType.LIST)) { + expect (TokenType.OF); + var m = parse_member_name (); + var expr = parse_list_creation_expression (begin, m); + return expr; + } + + if (accept (TokenType.DICT)) { + expect (TokenType.OF); + var m1 = parse_member_name (); + expect (TokenType.COMMA); + var m2 = parse_member_name (); + var expr = parse_dict_creation_expression (begin, m1, m2); + return expr; + } + + var member = parse_member_name (); if (accept (TokenType.OPEN_PARENS)) { var expr = parse_object_creation_expression (begin, member); @@ -884,6 +935,60 @@ public class Vala.Genie.Parser : CodeVisitor { } return expr; } + + + Expression parse_list_creation_expression (SourceLocation begin, MemberAccess member) throws ParseError { + + DataType element_type = UnresolvedType.new_from_expression (member); + MemberAccess list_member = null, parent_member = null; + + parent_member = new MemberAccess (null, "Gee", get_src (begin)); + list_member = new MemberAccess (parent_member, "ArrayList", get_src (begin)); + list_member.add_type_argument (element_type); + + list_member.creation_member = true; + + var expr = new ObjectCreationExpression (list_member, get_src (begin)); + + return expr; + } + + Expression parse_dict_creation_expression (SourceLocation begin, MemberAccess member_key, MemberAccess member_value) throws ParseError { + + DataType key_type = UnresolvedType.new_from_expression (member_key); + DataType value_type = UnresolvedType.new_from_expression (member_value); + + MemberAccess dict_member = null, parent_member = null, dict_hash = null, dict_equal = null; + + parent_member = new MemberAccess (null, "Gee", get_src (begin)); + dict_member = new MemberAccess (parent_member, "HashMap", get_src (begin)); + dict_member.add_type_argument (key_type); + dict_member.add_type_argument (value_type); + + if (member_key.member_name == "string") { + parent_member = new MemberAccess (null, "GLib", get_src (begin)); + dict_hash = new MemberAccess (parent_member, "str_hash", get_src (begin)); + dict_equal = new MemberAccess (parent_member, "str_equal", get_src (begin)); + + } else if (member_key.member_name == "int") { + parent_member = new MemberAccess (null, "GLib", get_src (begin)); + dict_hash = new MemberAccess (parent_member, "int_hash", get_src (begin)); + dict_equal = new MemberAccess (parent_member, "int_equal", get_src (begin)); + } + + dict_member.creation_member = true; + + var expr = new ObjectCreationExpression (dict_member, get_src (begin)); + + if (dict_hash != null && dict_equal != null) { + expr.add_argument (dict_hash); + expr.add_argument (dict_equal); + } + + + return expr; + } + Gee.List parse_object_initializer () throws ParseError { var list = new ArrayList (); @@ -2217,18 +2322,19 @@ public class Vala.Genie.Parser : CodeVisitor { } - bool add_uses_clause () throws ParseError { + void add_uses_clause () throws ParseError { var begin = get_location (); var sym = parse_symbol_name (); var ns_ref = new NamespaceReference (sym.name, get_src (begin)); scanner.source_file.add_using_directive (ns_ref); - - return (sym.name == "GLib"); + + if (sym.name == "GLib") { + has_uses_glib = true; + } } void parse_using_directives () throws ParseError { - var has_glib = false; var begin = get_location (); while (accept (TokenType.USES)) { var begin = get_location (); @@ -2237,9 +2343,7 @@ public class Vala.Genie.Parser : CodeVisitor { expect (TokenType.INDENT); while (current () != TokenType.DEDENT && current () != TokenType.EOF) { - if (add_uses_clause ()) { - has_glib = true; - } + add_uses_clause (); expect (TokenType.EOL); } @@ -2253,7 +2357,7 @@ public class Vala.Genie.Parser : CodeVisitor { } } - if (!has_glib) { + if (!has_uses_glib) { var ns_ref = new NamespaceReference ("GLib", get_src (begin)); scanner.source_file.add_using_directive (ns_ref); } @@ -2458,6 +2562,7 @@ public class Vala.Genie.Parser : CodeVisitor { return true; } + /* if (current () == TokenType.OPEN_PARENS) { var begin = get_location (); var is_array = false; @@ -2471,6 +2576,8 @@ public class Vala.Genie.Parser : CodeVisitor { return is_array; } + */ + return false; } diff --git a/vala/valageniescanner.vala b/vala/valageniescanner.vala index a46046f..478fef9 100644 --- a/vala/valageniescanner.vala +++ b/vala/valageniescanner.vala @@ -155,6 +155,9 @@ public class Vala.Genie.Scanner : Object { case 'c': if (matches (begin, "case")) return TokenType.CASE; break; + case 'd': + if (matches (begin, "dict")) return TokenType.DICT; + break; case 'e': switch (begin[1]) { case 'l': @@ -169,8 +172,16 @@ public class Vala.Genie.Scanner : Object { if (matches (begin, "init")) return TokenType.INIT; break; case 'l': - if (matches (begin, "lock")) return TokenType.LOCK; + switch (begin[1]) { + case 'i': + if (matches (begin, "list")) return TokenType.LIST; + break; + case 'o': + if (matches (begin, "lock")) return TokenType.LOCK; + break; + } break; + case 'n': if (matches (begin, "null")) return TokenType.NULL; break; diff --git a/vala/valagenietokentype.vala b/vala/valagenietokentype.vala index ef2c1b5..a2fd0ca 100644 --- a/vala/valagenietokentype.vala +++ b/vala/valagenietokentype.vala @@ -59,6 +59,7 @@ public enum Vala.Genie.TokenType { DEFAULT, DELEGATE, DELETE, + DICT, DIV, DO, DOT, @@ -94,6 +95,7 @@ public enum Vala.Genie.TokenType { IS, ISA, LAMBDA, + LIST, LOCK, MINUS, NAMESPACE, @@ -193,6 +195,7 @@ public enum Vala.Genie.TokenType { case DEFAULT: return "`default'"; case DELEGATE: return "`delegate'"; case DELETE: return "`delete'"; + case DICT: return "`dict'"; case DIV: return "`/'"; case DO: return "`do'"; case DOT: return "`.'"; @@ -228,6 +231,7 @@ public enum Vala.Genie.TokenType { case IS: return "`is'"; case ISA: return "`isa'"; case LAMBDA: return "`=>'"; + case LIST: return "`list'"; case LOCK: return "`lock'"; case MINUS: return "`-'"; case NAMESPACE: return "`namespace'"; -- 2.7.4