support prefix increment and decrement, fix parsing opening parens fix
authorJürg Billeter <j@bitron.ch>
Mon, 31 Jul 2006 09:45:56 +0000 (09:45 +0000)
committerJürg Billeter <juergbi@src.gnome.org>
Mon, 31 Jul 2006 09:45:56 +0000 (09:45 +0000)
2006-07-31  Jürg Billeter  <j@bitron.ch>

* vala/parser.y: support prefix increment and decrement, fix parsing
  opening parens
* vala/valasemanticanalyzer.vala: fix some bugs in error handling,
  support prefix increment and decrement
* vala/valacodegenerator.vala: support prefix increment and decrement
* vala/valanamespace.vala: add interface documentation, use implicit
  namespace specification
* vala/valaunaryexpression.vala: support prefix increment and decrement
* ccode/valaccodeunaryexpression.vala: support prefix increment and
  decrement
* vapi/glib-2.0.vala: add Environment struct

svn path=/trunk/; revision=87

vala/ChangeLog
vala/ccode/valaccodeunaryexpression.vala
vala/vala/parser.y
vala/vala/valacodegenerator.vala
vala/vala/valanamespace.vala
vala/vala/valasemanticanalyzer.vala
vala/vala/valaunaryexpression.vala
vala/vapi/glib-2.0.vala

index 69d3867..473cc00 100644 (file)
@@ -1,3 +1,17 @@
+2006-07-31  Jürg Billeter  <j@bitron.ch>
+
+       * vala/parser.y: support prefix increment and decrement, fix parsing
+         opening parens
+       * vala/valasemanticanalyzer.vala: fix some bugs in error handling,
+         support prefix increment and decrement
+       * vala/valacodegenerator.vala: support prefix increment and decrement
+       * vala/valanamespace.vala: add interface documentation, use implicit
+         namespace specification
+       * vala/valaunaryexpression.vala: support prefix increment and decrement
+       * ccode/valaccodeunaryexpression.vala: support prefix increment and
+         decrement
+       * vapi/glib-2.0.vala: add Environment struct
+
 2006-07-27  Jürg Billeter  <j@bitron.ch>
 
        * vala/scanner.l: support CASE, DEFAULT, DO, and SWITCH
index bf18ae5..0c4e535 100644 (file)
@@ -47,6 +47,10 @@ public class Vala.CCodeUnaryExpression : CCodeExpression {
                        writer.write_string ("~");
                } else if (operator == CCodeUnaryOperator.ADDRESS_OF) {
                        writer.write_string ("&");
+               } else if (operator == CCodeUnaryOperator.PREFIX_INCREMENT) {
+                       writer.write_string ("++");
+               } else if (operator == CCodeUnaryOperator.PREFIX_DECREMENT) {
+                       writer.write_string ("--");
                }
 
                inner.write (writer);
@@ -65,6 +69,8 @@ public enum Vala.CCodeUnaryOperator {
        LOGICAL_NEGATION,
        BITWISE_COMPLEMENT,
        ADDRESS_OF,
+       PREFIX_INCREMENT,
+       PREFIX_DECREMENT,
        POSTFIX_INCREMENT,
        POSTFIX_DECREMENT
 }
index b94b076..aa30ea4 100644 (file)
@@ -564,7 +564,7 @@ identifier_or_new
        ;
 
 invocation_expression
-       : primary_expression OPEN_PARENS opt_argument_list CLOSE_PARENS
+       : primary_expression open_parens opt_argument_list CLOSE_PARENS
          {
                ValaSourceReference *src = src(@1);
                $$ = VALA_EXPRESSION (vala_invocation_expression_new ($1, src));
@@ -616,7 +616,7 @@ post_decrement_expression
        ;
 
 object_creation_expression
-       : NEW type OPEN_PARENS opt_named_argument_list CLOSE_PARENS
+       : NEW type open_parens opt_named_argument_list CLOSE_PARENS
          {
                ValaSourceReference *src = src(@2);
                $$ = VALA_EXPRESSION (vala_object_creation_expression_new ($2, $4, src));
@@ -629,7 +629,7 @@ object_creation_expression
        ;
 
 typeof_expression
-       : TYPEOF OPEN_PARENS type_name CLOSE_PARENS
+       : TYPEOF open_parens type_name CLOSE_PARENS
          {
                ValaSourceReference *src = src(@1);
                $$ = VALA_EXPRESSION (vala_typeof_expression_new ($3, src));
@@ -660,6 +660,20 @@ unary_expression
                g_object_unref (src);
                g_object_unref ($2);
          }
+       | OP_INC unary_expression
+         {
+               ValaSourceReference *src = src(@1);
+               $$ = VALA_EXPRESSION (vala_unary_expression_new (VALA_UNARY_OPERATOR_INCREMENT, $2, src));
+               g_object_unref ($2);
+               g_object_unref (src);
+         }
+       | OP_DEC unary_expression
+         {
+               ValaSourceReference *src = src(@1);
+               $$ = VALA_EXPRESSION (vala_unary_expression_new (VALA_UNARY_OPERATOR_DECREMENT, $2, src));
+               g_object_unref ($2);
+               g_object_unref (src);
+         }
        | REF unary_expression
          {
                ValaSourceReference *src = src(@1);
@@ -1218,7 +1232,7 @@ selection_statement
        ;
 
 if_statement
-       : comment IF OPEN_PARENS expression CLOSE_PARENS embedded_statement
+       : comment IF open_parens expression CLOSE_PARENS embedded_statement
          {
                ValaSourceReference *src = src_com(@4, $1);
                $$ = VALA_STATEMENT (vala_if_statement_new ($4, $6, NULL, src));
@@ -1226,7 +1240,7 @@ if_statement
                g_object_unref ($4);
                g_object_unref ($6);
          }
-       | comment IF OPEN_PARENS expression CLOSE_PARENS embedded_statement ELSE embedded_statement
+       | comment IF open_parens expression CLOSE_PARENS embedded_statement ELSE embedded_statement
          {
                ValaSourceReference *src = src_com(@4, $1);
                $$ = VALA_STATEMENT (vala_if_statement_new ($4, $6, $8, src));
@@ -1238,7 +1252,7 @@ if_statement
        ;
 
 switch_statement
-       : comment SWITCH OPEN_PARENS expression CLOSE_PARENS switch_block
+       : comment SWITCH open_parens expression CLOSE_PARENS switch_block
          {
                ValaSourceReference *src = src_com(@4, $1);
                $$ = VALA_STATEMENT (vala_switch_statement_new ($4, src));
@@ -1338,7 +1352,7 @@ iteration_statement
        ;
 
 while_statement
-       : WHILE OPEN_PARENS expression CLOSE_PARENS embedded_statement
+       : WHILE open_parens expression CLOSE_PARENS embedded_statement
          {
                ValaSourceReference *src = src(@1);
                $$ = VALA_STATEMENT (vala_while_statement_new ($3, $5, src));
@@ -1349,7 +1363,7 @@ while_statement
        ;
 
 do_statement
-       : DO embedded_statement WHILE OPEN_PARENS expression CLOSE_PARENS SEMICOLON
+       : DO embedded_statement WHILE open_parens expression CLOSE_PARENS SEMICOLON
          {
                ValaSourceReference *src = src(@1);
                $$ = VALA_STATEMENT (vala_do_statement_new ($2, $5, src));
@@ -2789,6 +2803,11 @@ type_argument
        : type
        ;
 
+open_parens
+       : OPEN_PARENS
+       | OPEN_CAST_PARENS
+       ;
+
 %%
 
 extern FILE *yyin;
index 440fb1f..30b48e2 100644 (file)
@@ -2009,6 +2009,10 @@ public class Vala.CodeGenerator : CodeVisitor {
                        op = CCodeUnaryOperator.LOGICAL_NEGATION;
                } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) {
                        op = CCodeUnaryOperator.BITWISE_COMPLEMENT;
+               } else if (expr.operator == UnaryOperator.INCREMENT) {
+                       op = CCodeUnaryOperator.PREFIX_INCREMENT;
+               } else if (expr.operator == UnaryOperator.DECREMENT) {
+                       op = CCodeUnaryOperator.PREFIX_DECREMENT;
                } else if (expr.operator == UnaryOperator.REF) {
                        op = CCodeUnaryOperator.ADDRESS_OF;
                } else if (expr.operator == UnaryOperator.OUT) {
index aa57041..9dd0db9 100644 (file)
 
 using GLib;
 
-namespace Vala {
-       public class Namespace : CodeNode {
-               public string name { get; construct; }
-
-               List<Class> classes;
-               List<Interface> interfaces;
-               List<Struct> structs;
-               List<Enum> enums;
-               List<Flags> flags_;
-               List<Callback> callbacks;
-               List<Field> fields;
-               List<Method> methods;
-               
-               public string cprefix;
-               public string lower_case_cprefix;
-               
-               public static ref Namespace! new (string! name, SourceReference source) {
-                       return (new Namespace (name = name, source_reference = source));
-               }
-               
-               public void add_class (Class! cl) {
-                       classes.append (cl);
-                       cl.@namespace = this;
-               }
-               
-               public void remove_class (Class! cl) {
-                       classes.remove (cl);
-                       cl.@namespace = null;
-               }
-               
-               public void add_interface (Interface! iface) {
-                       interfaces.append (iface);
-                       iface.@namespace = this;
-               }
-               
-               public void add_struct (Struct! st) {
-                       structs.append (st);
-                       st.@namespace = this;
-               }
-               
-               public void remove_struct (Struct! st) {
-                       structs.remove (st);
-                       st.@namespace = null;
-               }
-                               
-               public void add_enum (Enum! en) {
-                       enums.append (en);
-                       en.@namespace = this;
-               }
-                               
-               public void add_flags (Flags! fl) {
-                       flags_.append (fl);
-                       fl.@namespace = this;
-               }
-                               
-               public void add_callback (Callback! cb) {
-                       callbacks.append (cb);
-                       cb.@namespace = this;
-               }
+/**
+ * Represents a namespace declaration in the source code.
+ */
+public class Vala.Namespace : CodeNode {
+       /**
+        * The name of this namespace.
+        */
+       public string name { get; set; }
 
-               public ref List<Struct> get_structs () {
-                       return structs.copy ();
-               }
+       private List<Class> classes;
+       private List<Interface> interfaces;
+       private List<Struct> structs;
+       private List<Enum> enums;
+       private List<Flags> flags_;
+       private List<Callback> callbacks;
+       private List<Field> fields;
+       private List<Method> methods;
+       
+       private string cprefix;
+       private string lower_case_cprefix;
+       
+       private List<string> cheader_filenames;
+       
+       /**
+        * Creates a new namespace.
+        *
+        * @param name   namespace name
+        * @param source reference to source code
+        * @return       newly created namespace
+        */
+       public static ref Namespace! new (string! name, SourceReference source) {
+               return (new Namespace (name = name, source_reference = source));
+       }
+       
+       /**
+        * Adds the specified class to this namespace.
+        *
+        * @param cl a class
+        */
+       public void add_class (Class! cl) {
+               classes.append (cl);
+               cl.@namespace = this;
+       }
+       
+       /**
+        * Adds the specified interface to this namespace.
+        *
+        * @param iface an interface
+        */
+       public void add_interface (Interface! iface) {
+               interfaces.append (iface);
+               iface.@namespace = this;
+       }
+       
+       /**
+        * Adds the specified struct to this namespace.
+        *
+        * @param st a struct
+        */
+       public void add_struct (Struct! st) {
+               structs.append (st);
+               st.@namespace = this;
+       }
+                       
+       /**
+        * Adds the specified enum to this namespace.
+        *
+        * @param en an enum
+        */
+       public void add_enum (Enum! en) {
+               enums.append (en);
+               en.@namespace = this;
+       }
+                       
+       /**
+        * Adds the specified flags to this namespace.
+        *
+        * @param fl a flags
+        */
+       public void add_flags (Flags! fl) {
+               flags_.append (fl);
+               fl.@namespace = this;
+       }
+       
+       /**
+        * Adds the specified callback to this namespace.
+        *
+        * @param cb a callback
+        */
+       public void add_callback (Callback! cb) {
+               callbacks.append (cb);
+               cb.@namespace = this;
+       }
 
-               public ref List<Class> get_classes () {
-                       return classes.copy ();
-               }
-               
-               public void add_field (Field! f) {
-                       fields.append (f);
-               }
-               
-               public void add_method (Method! m) {
-                       methods.append (m);
-               }
-               
-               public override void accept (CodeVisitor! visitor) {
-                       visitor.visit_begin_namespace (this);
+       /**
+        * Returns a copy of the list of structs.
+        *
+        * @return struct list
+        */
+       public ref List<Struct> get_structs () {
+               return structs.copy ();
+       }
 
-                       foreach (Class cl in classes) {
-                               cl.accept (visitor);
-                       }
+       /**
+        * Returns a copy of the list of classes.
+        *
+        * @return class list
+        */
+       public ref List<Class> get_classes () {
+               return classes.copy ();
+       }
+       
+       /**
+        * Adds the specified field to this namespace.
+        *
+        * @param f a field
+        */
+       public void add_field (Field! f) {
+               fields.append (f);
+       }
+       
+       /**
+        * Adds the specified method to this namespace.
+        *
+        * @param m a method
+        */
+       public void add_method (Method! m) {
+               methods.append (m);
+       }
+       
+       public override void accept (CodeVisitor! visitor) {
+               visitor.visit_begin_namespace (this);
 
-                       foreach (Interface iface in interfaces) {
-                               iface.accept (visitor);
-                       }
+               foreach (Class cl in classes) {
+                       cl.accept (visitor);
+               }
 
-                       foreach (Struct st in structs) {
-                               st.accept (visitor);
-                       }
+               foreach (Interface iface in interfaces) {
+                       iface.accept (visitor);
+               }
 
-                       foreach (Enum en in enums) {
-                               en.accept (visitor);
-                       }
+               foreach (Struct st in structs) {
+                       st.accept (visitor);
+               }
 
-                       foreach (Flags fl in flags_) {
-                               fl.accept (visitor);
-                       }
+               foreach (Enum en in enums) {
+                       en.accept (visitor);
+               }
 
-                       foreach (Callback cb in callbacks) {
-                               cb.accept (visitor);
-                       }
+               foreach (Flags fl in flags_) {
+                       fl.accept (visitor);
+               }
 
-                       foreach (Field f in fields) {
-                               f.accept (visitor);
-                       }
+               foreach (Callback cb in callbacks) {
+                       cb.accept (visitor);
+               }
 
-                       foreach (Method m in methods) {
-                               m.accept (visitor);
-                       }
+               foreach (Field f in fields) {
+                       f.accept (visitor);
+               }
 
-                       visitor.visit_end_namespace (this);
+               foreach (Method m in methods) {
+                       m.accept (visitor);
                }
 
-               public static ref string camel_case_to_lower_case (string camel_case) {
-                       String result = String.new ("");
-                       
-                       string i = camel_case;
-                       
-                       bool first = true;
-                       while (i.len () > 0) {
-                               unichar c = i.get_char ();
-                               if (c.isupper () && !first) {
-                                       /* current character is upper case and
-                                        * we're not at the beginning */
-                                       string t = i.prev_char ();
-                                       bool prev_upper = t.get_char ().isupper ();
-                                       t = i.next_char ();
-                                       bool next_upper = t.get_char ().isupper ();
-                                       if (!prev_upper || (i.len () >= 2 && !next_upper)) {
-                                               /* previous character wasn't upper case or
-                                                * next character isn't upper case*/
-                                               int len = result.str.len ();
-                                               if (len != 1 && result.str.offset (len - 2).get_char () != '_') {
-                                                       /* we're not creating 1 character words */
-                                                       result.append_c ('_');
-                                               }
+               visitor.visit_end_namespace (this);
+       }
+
+       /**
+        * Converts a string from CamelCase to lower_case.
+        *
+        * @param camel_case a string in camel case
+        * @return           the specified string converted to lower case
+        */
+       public static ref string! camel_case_to_lower_case (string! camel_case) {
+               String result = String.new ("");
+               
+               string i = camel_case;
+               
+               bool first = true;
+               while (i.len () > 0) {
+                       unichar c = i.get_char ();
+                       if (c.isupper () && !first) {
+                               /* current character is upper case and
+                                * we're not at the beginning */
+                               string t = i.prev_char ();
+                               bool prev_upper = t.get_char ().isupper ();
+                               t = i.next_char ();
+                               bool next_upper = t.get_char ().isupper ();
+                               if (!prev_upper || (i.len () >= 2 && !next_upper)) {
+                                       /* previous character wasn't upper case or
+                                        * next character isn't upper case*/
+                                       int len = result.str.len ();
+                                       if (len != 1 && result.str.offset (len - 2).get_char () != '_') {
+                                               /* we're not creating 1 character words */
+                                               result.append_c ('_');
                                        }
                                }
-                               
-                               result.append_unichar (c.tolower ());
-                               
-                               first = false;
-                               i = i.next_char ();
                        }
                        
-                       return result.str;
+                       result.append_unichar (c.tolower ());
+                       
+                       first = false;
+                       i = i.next_char ();
                }
                
-               public string get_cprefix () {
-                       if (cprefix == null) {
-                               if (name == null) {
-                                       cprefix = "";
-                               } else {
-                                       cprefix = name;
-                               }
+               return result.str;
+       }
+       
+       /**
+        * Returns the camel case string to be prepended to the name of members
+        * of this namespace when used in C code.
+        *
+        * @return the camel case prefix to be used in C code
+        */
+       public string! get_cprefix () {
+               if (cprefix == null) {
+                       if (name == null) {
+                               cprefix = "";
+                       } else {
+                               cprefix = name;
                        }
-                       return cprefix;
-               }
-               
-               public void set_cprefix (string cprefix) {
-                       this.cprefix = cprefix;
                }
-               
-               public string get_lower_case_cprefix () {
-                       if (lower_case_cprefix == null) {
-                               if (name == null) {
-                                       lower_case_cprefix = "";
-                               } else {
-                                       lower_case_cprefix = "%s_".printf (camel_case_to_lower_case (name));
-                               }
+               return cprefix;
+       }
+       
+       private void set_cprefix (string cprefix) {
+               this.cprefix = cprefix;
+       }
+       
+       /**
+        * Returns the lower case string to be prepended to the name of members
+        * of this namespace when used in C code.
+        *
+        * @return the lower case prefix to be used in C code
+        */
+       public string! get_lower_case_cprefix () {
+               if (lower_case_cprefix == null) {
+                       if (name == null) {
+                               lower_case_cprefix = "";
+                       } else {
+                               lower_case_cprefix = "%s_".printf (camel_case_to_lower_case (name));
                        }
-                       return lower_case_cprefix;
                }
-               
-               public void set_lower_case_cprefix (string cprefix) {
-                       this.lower_case_cprefix = cprefix;
-               }
-               
-               List<string> cheader_filenames;
-               
-               public ref List<string> get_cheader_filenames () {
-                       if (cheader_filenames == null) {
-                               cheader_filenames.append (source_reference.file.get_cheader_filename ());
-                       }
-                       return cheader_filenames.copy ();
+               return lower_case_cprefix;
+       }
+       
+       private void set_lower_case_cprefix (string cprefix) {
+               this.lower_case_cprefix = cprefix;
+       }
+       
+       /**
+        * Returns a list of C header filenames users of this namespace must
+        * include.
+        *
+        * @return list of C header filenames for this namespace
+        */
+       public ref List<string> get_cheader_filenames () {
+               if (cheader_filenames == null) {
+                       cheader_filenames.append (source_reference.file.get_cheader_filename ());
                }
-               
-               void process_ccode_attribute (Attribute! a) {
-                       foreach (NamedArgument arg in a.args) {
-                               if (arg.name == "cprefix") {
-                                       /* this will already be checked during semantic analysis */
-                                       if (arg.argument is LiteralExpression) {
-                                               var lit = ((LiteralExpression) arg.argument).literal;
-                                               if (lit is StringLiteral) {
-                                                       set_cprefix (((StringLiteral) lit).eval ());
-                                               }
+               return cheader_filenames.copy ();
+       }
+       
+       private void process_ccode_attribute (Attribute! a) {
+               foreach (NamedArgument arg in a.args) {
+                       if (arg.name == "cprefix") {
+                               /* this will already be checked during semantic analysis */
+                               if (arg.argument is LiteralExpression) {
+                                       var lit = ((LiteralExpression) arg.argument).literal;
+                                       if (lit is StringLiteral) {
+                                               set_cprefix (((StringLiteral) lit).eval ());
                                        }
-                               } else if (arg.name == "lower_case_cprefix") {
-                                       /* this will already be checked during semantic analysis */
-                                       if (arg.argument is LiteralExpression) {
-                                               var lit = ((LiteralExpression) arg.argument).literal;
-                                               if (lit is StringLiteral) {
-                                                       set_lower_case_cprefix (((StringLiteral) lit).eval ());
-                                               }
+                               }
+                       } else if (arg.name == "lower_case_cprefix") {
+                               /* this will already be checked during semantic analysis */
+                               if (arg.argument is LiteralExpression) {
+                                       var lit = ((LiteralExpression) arg.argument).literal;
+                                       if (lit is StringLiteral) {
+                                               set_lower_case_cprefix (((StringLiteral) lit).eval ());
                                        }
-                               } else if (arg.name == "cheader_filename") {
-                                       /* this will already be checked during semantic analysis */
-                                       if (arg.argument is LiteralExpression) {
-                                               var lit = ((LiteralExpression) arg.argument).literal;
-                                               if (lit is StringLiteral) {
-                                                       var val = ((StringLiteral) lit).eval ();
-                                                       foreach (string filename in val.split (",")) {
-                                                               cheader_filenames.append (filename);
-                                                       }
+                               }
+                       } else if (arg.name == "cheader_filename") {
+                               /* this will already be checked during semantic analysis */
+                               if (arg.argument is LiteralExpression) {
+                                       var lit = ((LiteralExpression) arg.argument).literal;
+                                       if (lit is StringLiteral) {
+                                               var val = ((StringLiteral) lit).eval ();
+                                               foreach (string filename in val.split (",")) {
+                                                       cheader_filenames.append (filename);
                                                }
                                        }
                                }
                        }
                }
-               
-               public void process_attributes () {
-                       foreach (Attribute a in attributes) {
-                               if (a.name == "CCode") {
-                                       process_ccode_attribute (a);
-                               }
+       }
+       
+       /**
+        * Process all associated attributes.
+        */
+       public void process_attributes () {
+               foreach (Attribute a in attributes) {
+                       if (a.name == "CCode") {
+                               process_ccode_attribute (a);
                        }
                }
        }
index ce1b1b7..53cbf01 100644 (file)
@@ -339,6 +339,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_if_statement (IfStatement! stmt) {
+               if (stmt.condition.error) {
+                       /* if there was an error in the condition, skip this check */
+                       stmt.error = true;
+                       return;
+               }
+               
                if (stmt.condition.static_type.data_type != bool_type.data_type) {
                        stmt.error = true;
                        Report.error (stmt.condition.source_reference, "Condition must be boolean");
@@ -519,6 +525,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                        var local_sym = ns.namespace_symbol.lookup (expr.member_name);
                                        if (local_sym != null) {
                                                if (expr.symbol_reference != null) {
+                                                       expr.error = true;
                                                        Report.error (expr.source_reference, "`%s' is an ambiguous reference between `%s' and `%s'".printf (expr.member_name, expr.symbol_reference.get_full_name (), local_sym.get_full_name ()));
                                                        return;
                                                }
@@ -529,6 +536,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                } else {
                        if (expr.inner.error) {
                                /* if there was an error in the inner expression, skip this check */
+                               expr.error = true;
                                return;
                        }
                
@@ -669,6 +677,12 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                
                var msym = expr.call.symbol_reference;
                
+               if (msym == null) {
+                       /* if no symbol found, skip this check */
+                       expr.error = true;
+                       return;
+               }
+               
                List<FormalParameter> params;
                
                if (msym.node is VariableDeclarator) {
@@ -811,8 +825,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }       
        
        public override void visit_element_access (ElementAccess! expr) {
-               if (expr.container.static_type == null || expr.index.static_type == null) {
+               if (expr.container.error || expr.index.error) {
                        /* don't proceed if a child expression failed */
+                       expr.error = true;
                        return;
                }
                
@@ -880,8 +895,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_unary_expression (UnaryExpression! expr) {
-               if (expr.inner.static_type == null) {
+               if (expr.inner.error) {
                        /* if there was an error in the inner expression, skip type check */
+                       expr.error = true;
                        return;
                }
        
@@ -897,6 +913,14 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        // integer type
 
                        expr.static_type = expr.inner.static_type;
+               } else if (expr.operator == UnaryOperator.INCREMENT) {
+                       // integer type
+
+                       expr.static_type = expr.inner.static_type;
+               } else if (expr.operator == UnaryOperator.DECREMENT) {
+                       // integer type
+
+                       expr.static_type = expr.inner.static_type;
                } else if (expr.operator == UnaryOperator.REF) {
                        // value type
 
@@ -906,7 +930,9 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
 
                        expr.static_type = expr.inner.static_type;
                } else {
-                       assert_not_reached ();
+                       expr.error = true;
+                       Report.error (expr.source_reference, "internal error: unsupported unary operator");
+                       return;
                }
        }
 
@@ -931,16 +957,18 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
        
        public override void visit_binary_expression (BinaryExpression! expr) {
-               if (expr.left.static_type == null
-                   || expr.right.static_type == null) {
+               if (expr.left.error || expr.right.error) {
                        /* if there were any errors in inner expressions, skip type check */
+                       expr.error = true;
                        return;
                }
        
                if (expr.left.static_type.data_type == string_type.data_type
                    && expr.operator == BinaryOperator.PLUS) {
                        if (expr.right.static_type.data_type != string_type.data_type) {
+                               expr.error = true;
                                Report.error (expr.source_reference, "Operands must be strings");
+                               return;
                        }
 
                        expr.static_type = string_type;
@@ -951,6 +979,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        // TODO: check for integer or floating point type in expr.left
 
                        if (!check_binary_type (expr, "Arithmetic operation")) {
+                               expr.error = true;
                                return;
                        }
 
@@ -962,6 +991,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        // TODO: check for integer type in expr.left
 
                        if (!check_binary_type (expr, "Arithmetic operation")) {
+                               expr.error = true;
                                return;
                        }
 
@@ -985,6 +1015,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                                /* TODO: check for integer or floating point type in expr.left */
 
                                if (!check_binary_type (expr, "Relational operation")) {
+                                       expr.error = true;
                                        return;
                                }
                        }
@@ -997,6 +1028,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        if (!is_type_compatible (expr.right.static_type, expr.left.static_type)
                            && !is_type_compatible (expr.left.static_type, expr.right.static_type)) {
                                Report.error (expr.source_reference, "Equality operation: `%s' and `%s' are incompatible, comparison would always evaluate to false".printf (expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
+                               expr.error = true;
                                return;
                        }
                        
@@ -1022,6 +1054,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                } else if (expr.operator == BinaryOperator.AND
                           || expr.operator == BinaryOperator.OR) {
                        if (expr.left.static_type.data_type != bool_type.data_type || expr.right.static_type.data_type != bool_type.data_type) {
+                               expr.error = true;
                                Report.error (expr.source_reference, "Operands must be boolean");
                        }
 
@@ -1034,6 +1067,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        public override void visit_type_check (TypeCheck! expr) {
                if (expr.type_reference.data_type == null) {
                        /* if type resolving didn't succeed, skip this check */
+                       expr.error = true;
                        return;
                }
        
@@ -1136,8 +1170,20 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_begin_assignment (Assignment! a) {
+               if (!(a.left is MemberAccess)) {
+                       a.error = true;
+                       Report.error (a.source_reference, "unsupported lvalue in assignment");
+                       return;
+               }
+       
                var ma = (MemberAccess) a.left;
                
+               if (ma.error || ma.symbol_reference == null) {
+                       a.error = true;
+                       /* if no symbol found, skip this check */
+                       return;
+               }
+               
                if (ma.symbol_reference.node is Signal) {
                        var sig = (Signal) ma.symbol_reference.node;
 
@@ -1147,9 +1193,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
        }
 
        public override void visit_end_assignment (Assignment! a) {
-               if (!(a.left is MemberAccess)) {
+               if (a.error || a.left.error || a.right.error) {
                        a.error = true;
-                       Report.error (a.source_reference, "unsupported lvalue in assignment");
                        return;
                }
        
@@ -1159,7 +1204,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
                        var sig = (Signal) ma.symbol_reference.node;
 
                        if (a.right.symbol_reference == null) {
-                               a.right.error = true;
+                               a.error = true;
                                Report.error (a.right.source_reference, "unsupported expression for signal handler");
                                return;
                        }
index 95a5b9d..11301a6 100644 (file)
@@ -62,6 +62,8 @@ public enum Vala.UnaryOperator {
        MINUS,
        LOGICAL_NEGATION,
        BITWISE_COMPLEMENT,
+       INCREMENT,
+       DECREMENT,
        REF,
        OUT
 }
index bdaf290..a1a086b 100644 (file)
@@ -84,30 +84,6 @@ public struct ulong {
        public ref string! to_string (string! format = "%lu");
 }
 
-[CCode (cname = "gint8", cheader_filename = "glib.h")]
-public struct int8 {
-}
-
-[CCode (cname = "guint8", cheader_filename = "glib.h")]
-public struct uint8 {
-}
-
-[CCode (cname = "gint16", cheader_filename = "glib.h")]
-public struct int16 {
-}
-
-[CCode (cname = "guint16", cheader_filename = "glib.h")]
-public struct uint16 {
-}
-
-[CCode (cname = "gint32", cheader_filename = "glib.h")]
-public struct int32 {
-}
-
-[CCode (cname = "guint32", cheader_filename = "glib.h")]
-public struct uint32 {
-}
-
 [CCode (cname = "gint64", cheader_filename = "glib.h", type_id = "G_TYPE_INT64", marshaller_type_name = "INT64")]
 public struct int64 {
 }
@@ -165,7 +141,9 @@ public struct string {
        [CCode (cname = "g_strcompress")]
        public ref string compress ();
        [CCode (cname = "g_strsplit")]
-       public ref string[] split (string delimiter, int max_tokens = 0);
+       public ref string[] split (string! delimiter, int max_tokens = 0);
+       [CCode (cname = "g_strsplit_set")]
+       public ref string[] split_set (string! delimiters, int max_tokens = 0);
        
        [CCode (cname = "g_utf8_next_char")]
        public string next_char ();
@@ -320,6 +298,19 @@ namespace GLib {
                public static ref string decode (string! text, ref ulong out_len);
        }
        
+       public struct Environment {
+               [CCode (cname = "g_get_application_name")]
+               public static string get_application_name ();
+               [CCode (cname = "g_set_application_name")]
+               public static void set_application_name (string application_name);
+               [CCode (cname = "g_get_user_name")]
+               public static string get_user_name ();
+               [CCode (cname = "g_get_host_name")]
+               public static string! get_host_name ();
+               [CCode (cname = "g_get_home_dir")]
+               public static string get_home_dir ();
+       }
+       
        public struct Path {
                public static ref string get_basename (string file_name);
                public static ref string get_dirname (string file_name);