+2006-05-31 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y: support interfaces, adapt to Class/Struct/Type changes,
+ improve error handling
+ * vala/valacodevisitor.vala: support interfaces
+ * vala/valasymbolbuilder.vala: improve error handling
+ * vala/valasymbolresolver.vala: use operators to compare strings
+ * vala/valasemanticanalyzer.vala: improve error handling, convert method
+ argument and type mismatch warnings to errors, add skeleton for
+ expressoin type checks, support string comparison operators
+ * vala/valacodegenerator.vala: fix warning, create structs for
+ interfaces, adapt to Class/Struct/Type changes, refactor and fix code
+ in visit_simple_name and visit_member_access, use operators to compare
+ strings
+ * vala/valainterfacewriter.vala: use operators to compare strings
+ * vala/valasourcefile.vala: fix warnings
+ * vala/valaclass.vala: don't inherit from Struct
+ * vala/valacodenode.vala: add error flag
+ * vala/valaconstant.vala: add get_cname method
+ * vala/valaenum.vala: override get_upper_case_cname method
+ * vala/valaenumvalue.vala: adapt to Class/Struct/Type changes
+ * vala/valafield.vala: use operators to compare strings
+ * vala/valainterface.vala
+ * vala/valainvocationexpression.vala: add add_argument method
+ * vala/valamethod.vala: adapt to Class/Struct/Type changes, use
+ operators to compare strings
+ * vala/valanamespace.vala: support interfaces, use operators to compare
+ strings
+ * vala/valastringliteral.vala: fix warning
+ * vala/valastruct.vala: inline visit_children method, use operators to
+ compare strings
+ * vala/valatype.vala: add abstract get_lower_case_cname method
+ * vala/valatypereference.vala: add to_string method
+ * vala/vala.h: update
+ * vala/Makefile.am: update
+ * vapi/glib-2.0.vala: small fixes
+
2006-05-26 Jürg Billeter <j@bitron.ch>
* vala/valasemanticanalyzer.vala: fix member access to namespaces
valaintegerliteral.c \
valaintegerliteral.h \
valaintegerliteral.vala \
+ valainterface.c \
+ valainterface.h \
+ valainterface.vala \
valainterfacewriter.c \
valainterfacewriter.h \
valainterfacewriter.vala \
static ValaSourceFile *current_source_file;
static ValaNamespace *current_namespace;
+static ValaClass *current_class;
static ValaStruct *current_struct;
+static ValaInterface *current_interface;
typedef enum {
VALA_MODIFIER_NONE,
ValaNamespace *namespace;
ValaClass *class;
ValaStruct *struct_;
+ ValaInterface *interface;
ValaEnum *enum_;
ValaEnumValue *enum_value;
ValaConstant *constant;
%type <property_accessor> set_accessor_declaration
%type <struct_> struct_declaration
%type <struct_> struct_header
+%type <interface> interface_declaration
+%type <method> interface_method_declaration
+%type <property> interface_property_declaration
+%type <property_accessor> interface_get_accessor_declaration
+%type <property_accessor> opt_interface_set_accessor_declaration
+%type <property_accessor> interface_set_accessor_declaration
%type <enum_> enum_declaration
%type <list> enum_body
%type <list> opt_enum_member_declarations
expression
: conditional_expression
| assignment
+ | error
+ {
+ $$ = NULL;
+ }
;
statement
namespace_member_declaration
: class_declaration
{
- vala_namespace_add_class (current_namespace, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_namespace_add_class (current_namespace, $1);
+ }
}
| struct_declaration
{
- vala_namespace_add_struct (current_namespace, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_namespace_add_struct (current_namespace, $1);
+ }
}
| interface_declaration
+ {
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_namespace_add_interface (current_namespace, $1);
+ }
+ }
| enum_declaration
{
- vala_namespace_add_enum (current_namespace, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_namespace_add_enum (current_namespace, $1);
+ }
}
| flags_declaration
| field_declaration
{
- vala_namespace_add_field (current_namespace, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_namespace_add_field (current_namespace, $1);
+ }
}
| method_declaration
{
- vala_namespace_add_method (current_namespace, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_namespace_add_method (current_namespace, $1);
+ }
}
;
: comment opt_attributes opt_access_modifier opt_modifiers CLASS IDENTIFIER opt_type_parameter_list opt_class_base
{
GList *l;
- current_struct = VALA_STRUCT (vala_class_new ($6, src_com (@6, $1)));
- VALA_CODE_NODE(current_struct)->attributes = $2;
+ current_class = vala_class_new ($6, src_com (@6, $1));
+ VALA_CODE_NODE(current_class)->attributes = $2;
if ($3 != 0) {
- VALA_TYPE_(current_struct)->access = $3;
+ VALA_TYPE_(current_class)->access = $3;
}
for (l = $7; l != NULL; l = l->next) {
- vala_struct_add_type_parameter (current_struct, l->data);
+ vala_class_add_type_parameter (current_class, l->data);
}
for (l = $8; l != NULL; l = l->next) {
- vala_class_add_base_type (VALA_CLASS (current_struct), l->data);
+ vala_class_add_base_type (current_class, l->data);
}
}
class_body
{
- $$ = VALA_CLASS (current_struct);
- current_struct = NULL;
+ $$ = current_class;
+ current_class = NULL;
}
;
class_member_declaration
: constant_declaration
{
- vala_struct_add_constant (current_struct, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_class_add_constant (current_class, $1);
+ }
}
| field_declaration
{
- vala_struct_add_field (current_struct, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_class_add_field (current_class, $1);
+ }
}
| method_declaration
{
- vala_struct_add_method (current_struct, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_class_add_method (current_class, $1);
+ }
}
| property_declaration
{
- vala_class_add_property (VALA_CLASS (current_struct), $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_class_add_property (current_class, $1);
+ }
}
;
struct_member_declaration
: field_declaration
{
- vala_struct_add_field (current_struct, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_struct_add_field (current_struct, $1);
+ }
}
| method_declaration
{
- vala_struct_add_method (current_struct, $1);
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_struct_add_method (current_struct, $1);
+ }
}
;
interface_declaration
- : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER interface_body
+ : comment opt_attributes opt_access_modifier INTERFACE IDENTIFIER
+ {
+ current_interface = vala_interface_new ($5, src_com (@5, $1));
+ }
+ interface_body
+ {
+ $$ = current_interface;
+ }
;
interface_body
;
interface_member_declaration
- : method_declaration
+ : interface_method_declaration
+ {
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_interface_add_method (current_interface, $1);
+ }
+ }
+ | interface_property_declaration
+ {
+ /* skip declarations with errors */
+ if ($1 != NULL) {
+ vala_interface_add_property (current_interface, $1);
+ }
+ }
+ ;
+
+interface_method_declaration
+ : comment opt_attributes opt_ref type identifier_or_new OPEN_PARENS opt_formal_parameter_list CLOSE_PARENS SEMICOLON
+ {
+ GList *l;
+
+ $$ = vala_method_new ($5, $4, src_com (@5, $1));
+ $$->access = VALA_MEMBER_ACCESSIBILITY_PUBLIC;
+ $$->is_abstract = TRUE;
+ VALA_CODE_NODE($$)->attributes = $2;
+
+ for (l = $7; l != NULL; l = l->next) {
+ vala_method_add_parameter ($$, l->data);
+ }
+ }
+ ;
+
+interface_property_declaration
+ : comment opt_attributes opt_ref type IDENTIFIER OPEN_BRACE interface_get_accessor_declaration opt_interface_set_accessor_declaration CLOSE_BRACE
+ {
+ $$ = vala_property_new ($5, $4, $7, $8, src_com (@4, $1));
+ }
+ | comment opt_attributes opt_ref type IDENTIFIER OPEN_BRACE interface_set_accessor_declaration CLOSE_BRACE
+ {
+ $$ = vala_property_new ($5, $4, NULL, $7, src_com (@4, $1));
+ }
+ ;
+
+interface_get_accessor_declaration
+ : opt_attributes GET SEMICOLON
+ {
+ $$ = vala_property_accessor_new (TRUE, FALSE, FALSE, NULL, src (@2));
+ }
+ ;
+
+opt_interface_set_accessor_declaration
+ : /* empty */
+ {
+ $$ = NULL;
+ }
+ | interface_set_accessor_declaration
+ ;
+
+interface_set_accessor_declaration
+ : opt_attributes SET SEMICOLON
+ {
+ $$ = vala_property_accessor_new (FALSE, TRUE, FALSE, NULL, src (@2));
+ }
+ | opt_attributes SET CONSTRUCT SEMICOLON
+ {
+ $$ = vala_property_accessor_new (FALSE, TRUE, TRUE, NULL, src (@2));
+ }
+ | opt_attributes CONSTRUCT SEMICOLON
+ {
+ $$ = vala_property_accessor_new (FALSE, FALSE, TRUE, NULL, src (@2));
+ }
;
enum_declaration
static void
yyerror (YYLTYPE *locp, ValaParser *parser, const char *msg)
{
- printf ("%s:%d.%d-%d.%d: %s\n", vala_source_file_get_filename (current_source_file), locp->first_line, locp->first_column, locp->last_line, locp->last_column, msg);
+ ValaSourceReference *source_reference = vala_source_reference_new (current_source_file, locp->first_line, locp->first_column, locp->last_line, locp->last_column);
+ vala_report_error (source_reference, msg);
}
void
#include <vala/valaifstatement.h>
#include <vala/valainitializerlist.h>
#include <vala/valaintegerliteral.h>
+#include <vala/valainterface.h>
#include <vala/valainvocationexpression.h>
#include <vala/valaliteral.h>
#include <vala/valaliteralexpression.h>
using GLib;
namespace Vala {
- public class Class : Struct {
+ public class Class : Type_ {
+ List<string> type_parameters;
public List<TypeReference> base_types;
public Class base_class;
public bool is_abstract;
+ List<Constant> constants;
+ List<Field> fields;
+ List<Method> methods;
List<Property> properties;
+
+ public string cname;
+ public string lower_case_csuffix;
+ public bool has_private_fields;
+
+ public static ref Class new (string name, SourceReference source) {
+ return (new Class (name = name, source_reference = source));
+ }
public void add_base_type (TypeReference type) {
base_types.append (type);
}
+
+ public void add_type_parameter (TypeParameter p) {
+ type_parameters.append (p);
+ p.type = this;
+ }
- public static ref Class new (string name, SourceReference source) {
- return (new Class (name = name, source_reference = source));
+ public void add_constant (Constant c) {
+ constants.append (c);
+ }
+
+ public void add_field (Field f) {
+ fields.append (f);
+ if (f.access == MemberAccessibility.PRIVATE) {
+ has_private_fields = true;
+ }
+ }
+
+ public ref List<Field> get_fields () {
+ return fields.copy ();
+ }
+
+ public void add_method (Method m) {
+ return_if_fail (m != null);
+
+ methods.append (m);
+ }
+
+ public ref List<Method> get_methods () {
+ return methods.copy ();
}
public void add_property (Property prop) {
type.accept (visitor);
}
- visit_children (visitor);
+ foreach (TypeParameter p in type_parameters) {
+ p.accept (visitor);
+ }
+
+ foreach (Field f in fields) {
+ f.accept (visitor);
+ }
+
+ foreach (Constant c in constants) {
+ c.accept (visitor);
+ }
+
+ foreach (Method m in methods) {
+ m.accept (visitor);
+ }
foreach (Property prop in properties) {
prop.accept (visitor);
visitor.visit_end_class (this);
}
+
+ public override string get_cname () {
+ if (cname == null) {
+ cname = "%s%s".printf (@namespace.get_cprefix (), name);
+ }
+ return cname;
+ }
+
+ public void set_cname (string cname) {
+ this.cname = cname;
+ }
+
+ public string get_lower_case_csuffix () {
+ if (lower_case_csuffix == null) {
+ lower_case_csuffix = Namespace.camel_case_to_lower_case (name);
+ }
+ return lower_case_csuffix;
+ }
+
+ public void set_lower_case_csuffix (string csuffix) {
+ this.lower_case_csuffix = csuffix;
+ }
+
+ public override ref string get_lower_case_cname (string infix) {
+ if (infix == null) {
+ infix = "";
+ }
+ return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
+ }
+
+ public override ref string get_upper_case_cname (string infix) {
+ return get_lower_case_cname (infix).up (-1);
+ }
public override bool is_reference_type () {
return true;
}
+
+ void process_ccode_attribute (Attribute a) {
+ foreach (NamedArgument arg in a.args) {
+ if (arg.name == "cname") {
+ /* this will already be checked during semantic analysis */
+ if (arg.argument is LiteralExpression) {
+ var lit = ((LiteralExpression) arg.argument).literal;
+ if (lit is StringLiteral) {
+ set_cname (((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 (",", 0)) {
+ cheader_filenames.append (filename);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public void process_attributes () {
+ foreach (Attribute a in attributes) {
+ if (a.name == "CCode") {
+ process_ccode_attribute (a);
+ }
+ }
+ }
}
}
CCodeFragment source_type_member_definition;
CCodeStruct instance_struct;
- CCodeStruct class_struct;
+ CCodeStruct type_struct;
CCodeStruct instance_priv_struct;
CCodeEnum prop_enum;
CCodeEnum cenum;
var i = filename;
while (i.len (-1) > 0) {
var c = i.get_char ();
- if (c.isalnum () && c < 128) {
+ /* FIXME: remove explicit cast when implicit cast works */
+ if (c.isalnum () && c < (unichar) 128) {
define.append_unichar (c.toupper ());
} else {
define.append_c ('_');
current_symbol = cl.symbol;
instance_struct = new CCodeStruct (name = "_%s".printf (cl.get_cname ()));
- class_struct = new CCodeStruct (name = "_%sClass".printf (cl.get_cname ()));
+ type_struct = new CCodeStruct (name = "_%sClass".printf (cl.get_cname ()));
instance_priv_struct = new CCodeStruct (name = "_%sPrivate".printf (cl.get_cname ()));
prop_enum = new CCodeEnum ();
prop_enum.add_value ("%s_DUMMY_PROPERTY".printf (cl.get_upper_case_cname (null)), null);
if (cl.source_reference.file.cycle == null) {
header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_struct.name), typedef_name = cl.get_cname ()));
- header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (class_struct.name), typedef_name = "%sClass".printf (cl.get_cname ())));
+ header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (type_struct.name), typedef_name = "%sClass".printf (cl.get_cname ())));
}
header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (instance_priv_struct.name), typedef_name = "%sPrivate".printf (cl.get_cname ())));
instance_struct.add_field (cl.base_class.get_cname (), "parent");
instance_struct.add_field ("%sPrivate *".printf (cl.get_cname ()), "priv");
- class_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent");
+ type_struct.add_field ("%sClass".printf (cl.base_class.get_cname ()), "parent");
if (cl.source_reference.comment != null) {
header_type_definition.append (new CCodeComment (text = cl.source_reference.comment));
}
header_type_definition.append (instance_struct);
- header_type_definition.append (class_struct);
+ header_type_definition.append (type_struct);
source_type_member_declaration.append (instance_priv_struct);
macro = "(G_TYPE_INSTANCE_GET_PRIVATE ((o), %s, %sPrivate))".printf (cl.get_upper_case_cname ("TYPE_"), cl.get_cname ());
source_type_member_declaration.append (new CCodeMacroReplacement (name = "%s_GET_PRIVATE(o)".printf (cl.get_upper_case_cname (null)), replacement = macro));
if (prop.type_reference.type is Class) {
cspec.call = new CCodeIdentifier (name = "g_param_spec_object");
cspec.add_argument (new CCodeIdentifier (name = prop.type_reference.type.get_upper_case_cname ("TYPE_")));
- } else if (prop.type_reference.type_name.collate ("string") == 0) {
+ } else if (prop.type_reference.type_name == "string") {
cspec.call = new CCodeIdentifier (name = "g_param_spec_string");
cspec.add_argument (new CCodeConstant (name = "NULL"));
- } else if (prop.type_reference.type_name.collate ("int") == 0 || prop.type_reference.type is Enum) {
+ } else if (prop.type_reference.type_name == "int"
+ || prop.type_reference.type is Enum) {
cspec.call = new CCodeIdentifier (name = "g_param_spec_int");
cspec.add_argument (new CCodeConstant (name = "G_MININT"));
cspec.add_argument (new CCodeConstant (name = "G_MAXINT"));
cspec.add_argument (new CCodeConstant (name = "0"));
- } else if (prop.type_reference.type_name.collate ("bool") == 0) {
+ } else if (prop.type_reference.type_name == "bool") {
cspec.call = new CCodeIdentifier (name = "g_param_spec_boolean");
cspec.add_argument (new CCodeConstant (name = "FALSE"));
} else {
var csetcall = new CCodeFunctionCall ();
if (prop.type_reference.type is Class) {
csetcall.call = new CCodeIdentifier (name = "g_value_set_object");
- } else if (prop.type_reference.type_name.collate ("string") == 0) {
+ } else if (prop.type_reference.type_name == "string") {
csetcall.call = new CCodeIdentifier (name = "g_value_set_string");
- } else if (prop.type_reference.type_name.collate ("int") == 0 || prop.type_reference.type is Enum) {
+ } else if (prop.type_reference.type_name == "int"
+ || prop.type_reference.type is Enum) {
csetcall.call = new CCodeIdentifier (name = "g_value_set_int");
- } else if (prop.type_reference.type_name.collate ("bool") == 0) {
+ } else if (prop.type_reference.type_name == "bool") {
csetcall.call = new CCodeIdentifier (name = "g_value_set_boolean");
} else {
csetcall.call = new CCodeIdentifier (name = "g_value_set_pointer");
var cgetcall = new CCodeFunctionCall ();
if (prop.type_reference.type is Class) {
cgetcall.call = new CCodeIdentifier (name = "g_value_get_object");
- } else if (prop.type_reference.type_name.collate ("string") == 0) {
+ } else if (prop.type_reference.type_name == "string") {
cgetcall.call = new CCodeIdentifier (name = "g_value_dup_string");
- } else if (prop.type_reference.type_name.collate ("int") == 0 || prop.type_reference.type is Enum) {
+ } else if (prop.type_reference.type_name == "int"
+ || prop.type_reference.type is Enum) {
cgetcall.call = new CCodeIdentifier (name = "g_value_get_int");
- } else if (prop.type_reference.type_name.collate ("bool") == 0) {
+ } else if (prop.type_reference.type_name == "bool") {
cgetcall.call = new CCodeIdentifier (name = "g_value_get_boolean");
} else {
cgetcall.call = new CCodeIdentifier (name = "g_value_get_pointer");
}
header_type_definition.append (instance_struct);
}
+
+ public override void visit_begin_interface (Interface iface) {
+ current_symbol = iface.symbol;
+
+ type_struct = new CCodeStruct (name = "_%sInterface".printf (iface.get_cname ()));
+
+ header_type_declaration.append (new CCodeNewline ());
+ var macro = "(%s_get_type ())".printf (iface.get_lower_case_cname (null));
+ header_type_declaration.append (new CCodeMacroReplacement (name = iface.get_upper_case_cname ("TYPE_"), replacement = macro));
+
+ macro = "(G_TYPE_CHECK_INSTANCE_CAST ((obj), %s, %s))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ());
+ header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (iface.get_upper_case_cname (null)), replacement = macro));
+
+ macro = "(G_TYPE_CHECK_INSTANCE_TYPE ((obj), %s))".printf (iface.get_upper_case_cname ("TYPE_"));
+ header_type_declaration.append (new CCodeMacroReplacement (name = "%s(obj)".printf (iface.get_upper_case_cname ("IS_")), replacement = macro));
+
+ macro = "(G_TYPE_INSTANCE_GET_INTERFACE ((obj), %s, %sInterface))".printf (iface.get_upper_case_cname ("TYPE_"), iface.get_cname ());
+ header_type_declaration.append (new CCodeMacroReplacement (name = "%s_GET_INTERFACE(obj)".printf (iface.get_upper_case_cname (null)), replacement = macro));
+ header_type_declaration.append (new CCodeNewline ());
+
+
+ if (iface.source_reference.file.cycle == null) {
+ header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct _%s".printf (iface.get_cname ()), typedef_name = iface.get_cname ()));
+ header_type_declaration.append (new CCodeTypeDefinition (type_name = "struct %s".printf (type_struct.name), typedef_name = "%sInterface".printf (iface.get_cname ())));
+ }
+
+ type_struct.add_field ("GTypeInterface", "parent");
+
+ if (iface.source_reference.comment != null) {
+ header_type_definition.append (new CCodeComment (text = iface.source_reference.comment));
+ }
+ header_type_definition.append (type_struct);
+ }
+
+ public override void visit_end_interface (Interface iface) {
+ }
public override void visit_begin_enum (Enum en) {
cenum = new CCodeEnum (name = en.get_cname ());
}
public override void visit_constant (Constant c) {
- if (c.symbol.parent_symbol.node is Struct) {
- var t = (Struct) c.symbol.parent_symbol.node;
+ if (c.symbol.parent_symbol.node is Type_) {
+ var t = (Type_) c.symbol.parent_symbol.node;
var cdecl = new CCodeDeclaration (type_name = c.type_reference.get_const_cname ());
var arr = "";
if (c.type_reference.array) {
if (f.instance) {
instance_priv_struct.add_field (f.type_reference.get_cname (), f.get_cname ());
} else {
- if (f.symbol.parent_symbol.node is Struct) {
- var t = (Struct) f.symbol.parent_symbol.node;
+ if (f.symbol.parent_symbol.node is Type_) {
+ var t = (Type_) f.symbol.parent_symbol.node;
var cdecl = new CCodeDeclaration (type_name = f.type_reference.get_cname ());
cdecl.add_declarator (new CCodeVariableDeclarator (name = "%s_%s".printf (t.get_lower_case_cname (null), f.get_cname ())));
cdecl.modifiers = CCodeModifiers.STATIC;
}
public override void visit_end_method (Method m) {
- if (m.name.collate ("init") == 0) {
+ if (m.name == "init") {
return;
}
CCodeFunctionDeclarator vdeclarator = null;
if (m.instance) {
- var st = (Struct) m.symbol.parent_symbol.node;
var this_type = new TypeReference ();
- this_type.type = st;
+ this_type.type = (Type_) m.symbol.parent_symbol.node;
if (!m.is_override) {
var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self");
function.add_parameter (cparam);
var vdecl = new CCodeDeclaration (type_name = m.return_type.get_cname ());
vdeclarator = new CCodeFunctionDeclarator (name = m.name);
vdecl.add_declarator (vdeclarator);
- class_struct.add_declaration (vdecl);
+ type_struct.add_declaration (vdecl);
var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self");
vdeclarator.add_parameter (cparam);
var vfunc = new CCodeFunction (name = m.get_cname (), return_type = m.return_type.get_cname ());
- var st = (Struct) m.symbol.parent_symbol.node;
var this_type = new TypeReference ();
- this_type.type = st;
+ this_type.type = (Type_) m.symbol.parent_symbol.node;
var cparam = new CCodeFormalParameter (type_name = this_type.get_cname (), name = "self");
vfunc.add_parameter (cparam);
source_type_member_definition.append (vfunc);
}
- if (m.name.collate ("main") == 0) {
+ if (m.name == "main") {
var cmain = new CCodeFunction (name = "main", return_type = "int");
cmain.add_parameter (new CCodeFormalParameter (type_name = "int", name = "argc"));
cmain.add_parameter (new CCodeFormalParameter (type_name = "char **", name = "argv"));
}
}
- public override void visit_begin_property (Property prop) {
- }
-
public override void visit_end_property (Property prop) {
prop_enum.add_value (prop.get_upper_case_cname (), null);
}
- public override void visit_begin_property_accessor (PropertyAccessor acc) {
- }
-
public override void visit_end_property_accessor (PropertyAccessor acc) {
var prop = (Property) acc.symbol.parent_symbol.node;
var cl = (Class) prop.symbol.parent_symbol.node;
cfor.add_initializer (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = (CCodeExpression) stmt.collection.ccodenode));
cfor.add_iterator (new CCodeAssignment (left = new CCodeIdentifier (name = it_name), right = new CCodeBinaryExpression (operator = CCodeBinaryOperator.PLUS, left = new CCodeIdentifier (name = it_name), right = new CCodeConstant (name = "1"))));
cblock.add_statement (cfor);
- } else if (stmt.collection.static_type.type.name.collate ("List") == 0) {
+ } else if (stmt.collection.static_type.type.name == "List") {
var it_name = "%s_it".printf (stmt.variable_name);
var citdecl = new CCodeDeclaration (type_name = "GList *");
expr.ccodenode = expr.literal.ccodenode;
}
- public override void visit_simple_name (SimpleName expr) {
- if (expr.name.collate ("this") == 0) {
- expr.ccodenode = new CCodeIdentifier (name = "self");
- } else if (expr.symbol_reference.node is Method) {
+ private void process_cmember (Expression expr, CCodeIdentifier pub_inst, Type_ base_type) {
+ if (expr.symbol_reference.node is Method) {
var m = (Method) expr.symbol_reference.node;
- expr.ccodenode = new CCodeIdentifier (name = m.get_cname ());
+ if (!m.is_override) {
+ expr.ccodenode = new CCodeIdentifier (name = m.get_cname ());
+ } else {
+ expr.ccodenode = new CCodeIdentifier (name = m.base_method.get_cname ());
+ }
} else if (expr.symbol_reference.node is Field) {
var f = (Field) expr.symbol_reference.node;
if (f.instance) {
- var pub_inst = new CCodeIdentifier (name = "self");
ref CCodeExpression typed_inst;
- if (f.symbol.parent_symbol != current_symbol) {
+ if (f.symbol.parent_symbol.node != base_type) {
typed_inst = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((Type_) f.symbol.parent_symbol.node).get_upper_case_cname (null)));
((CCodeFunctionCall) typed_inst).add_argument (pub_inst);
} else {
}
expr.ccodenode = new CCodeMemberAccess (inner = inst, member_name = f.get_cname (), is_pointer = true);
} else {
- if (f.symbol.parent_symbol.node is Struct) {
- var t = (Struct) f.symbol.parent_symbol.node;
+ if (f.symbol.parent_symbol.node is Type_) {
+ var t = (Type_) f.symbol.parent_symbol.node;
expr.ccodenode = new CCodeIdentifier (name = "%s_%s".printf (t.get_lower_case_cname (null), f.get_cname ()));
} else {
expr.ccodenode = new CCodeIdentifier (name = f.get_cname ());
}
} else if (expr.symbol_reference.node is Constant) {
var c = (Constant) expr.symbol_reference.node;
- if (c.symbol.parent_symbol.node is Struct) {
- var t = (Struct) c.symbol.parent_symbol.node;
- expr.ccodenode = new CCodeIdentifier (name = "%s_%s".printf (t.get_lower_case_cname (null), expr.name));
- } else {
- expr.ccodenode = new CCodeIdentifier (name = expr.name);
- }
+ expr.ccodenode = new CCodeIdentifier (name = c.get_cname ());
} else if (expr.symbol_reference.node is Property) {
var prop = (Property) expr.symbol_reference.node;
var cl = (Class) prop.symbol.parent_symbol.node;
var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name)));
- ccall.add_argument (new CCodeIdentifier (name = "self"));
+ ccall.add_argument (pub_inst);
expr.ccodenode = ccall;
- } else {
- expr.ccodenode = new CCodeIdentifier (name = expr.name);
+ } else if (expr.symbol_reference.node is EnumValue) {
+ var ev = (EnumValue) expr.symbol_reference.node;
+ expr.ccodenode = new CCodeConstant (name = ev.get_cname ());
+ } else if (expr.symbol_reference.node is VariableDeclarator) {
+ var decl = (VariableDeclarator) expr.symbol_reference.node;
+ expr.ccodenode = new CCodeIdentifier (name = decl.name);
+ } else if (expr.symbol_reference.node is FormalParameter) {
+ var p = (FormalParameter) expr.symbol_reference.node;
+ if (p.name == "this") {
+ expr.ccodenode = pub_inst;
+ } else {
+ expr.ccodenode = new CCodeIdentifier (name = p.name);
+ }
}
}
+
+ public override void visit_simple_name (SimpleName expr) {
+ var pub_inst = new CCodeIdentifier (name = "self");
+ var base_type = (Type_) current_symbol.node;
+
+ process_cmember (expr, pub_inst, base_type);
+ }
public override void visit_parenthesized_expression (ParenthesizedExpression expr) {
expr.ccodenode = new CCodeParenthesizedExpression (inner = (CCodeExpression) expr.inner.ccodenode);
}
public override void visit_member_access (MemberAccess expr) {
- if (expr.symbol_reference.node is Method) {
- var m = (Method) expr.symbol_reference.node;
- if (!m.is_override) {
- expr.ccodenode = new CCodeIdentifier (name = m.get_cname ());
- } else {
- expr.ccodenode = new CCodeIdentifier (name = m.base_method.get_cname ());
- }
- } else if (expr.symbol_reference.node is Field) {
- var f = (Field) expr.symbol_reference.node;
- var pub_inst = expr.inner.ccodenode;
- ref CCodeExpression typed_inst;
- if (f.symbol.parent_symbol.node != expr.inner.static_type.type) {
- typed_inst = new CCodeFunctionCall (call = new CCodeIdentifier (name = ((Type_) f.symbol.parent_symbol.node).get_upper_case_cname (null)));
- ((CCodeFunctionCall) typed_inst).add_argument (pub_inst);
- } else {
- typed_inst = pub_inst;
- }
- ref CCodeExpression inst;
- if (f.access == MemberAccessibility.PRIVATE) {
- inst = new CCodeMemberAccess (inner = typed_inst, member_name = "priv", is_pointer = true);
- } else {
- inst = typed_inst;
- }
- expr.ccodenode = new CCodeMemberAccess (inner = inst, member_name = f.get_cname (), is_pointer = true);
- } else if (expr.symbol_reference.node is Property) {
- var prop = (Property) expr.symbol_reference.node;
- var cl = (Class) prop.symbol.parent_symbol.node;
- var ccall = new CCodeFunctionCall (call = new CCodeIdentifier (name = "%s_get_%s".printf (cl.get_lower_case_cname (null), prop.name)));
- ccall.add_argument (expr.inner.ccodenode);
- expr.ccodenode = ccall;
- } else if (expr.symbol_reference.node is EnumValue) {
- var ev = (EnumValue) expr.symbol_reference.node;
- expr.ccodenode = new CCodeConstant (name = ev.get_cname ());
- } else {
- expr.ccodenode = new CCodeMemberAccess (inner = (CCodeExpression) expr.inner.ccodenode, member_name = expr.member_name, is_pointer = true);
+ var pub_inst = expr.inner.ccodenode;
+ Type_ base_type = null;
+ if (expr.inner.static_type != null) {
+ base_type = expr.inner.static_type.type;
}
+
+ process_cmember (expr, pub_inst, base_type);
}
public override void visit_invocation_expression (InvocationExpression expr) {
public Symbol symbol;
public List<Attribute> attributes;
public CCodeNode ccodenode;
+ public bool error;
public abstract void accept (CodeVisitor visitor);
}
public virtual void visit_end_struct (Struct st) {
}
+ public virtual void visit_begin_interface (Interface iface) {
+ }
+
+ public virtual void visit_end_interface (Interface iface) {
+ }
+
public virtual void visit_begin_enum (Enum en) {
}
visitor.visit_constant (this);
}
+
+ string cname;
+ public string get_cname () {
+ if (cname == null) {
+ if (symbol.parent_symbol.node is Type_) {
+ var t = (Type_) symbol.parent_symbol.node;
+ cname = "%s_%s".printf (t.get_upper_case_cname (null), name);
+ } else {
+ var ns = (Namespace) symbol.parent_symbol.node;
+ cname = "%s%s".printf (ns.get_cprefix ().up (-1), name);
+ }
+ }
+ return cname;
+ }
}
}
return cname;
}
- public string get_upper_case_cname () {
+ public override string get_upper_case_cname (string infix) {
return "%s%s".printf (@namespace.get_lower_case_cprefix (), Namespace.camel_case_to_lower_case (name)).up (-1);
}
public string get_cname () {
if (cname == null) {
var en = (Enum) symbol.parent_symbol.node;
- cname = "%s_%s".printf (en.get_upper_case_cname (), name);
+ cname = "%s_%s".printf (en.get_upper_case_cname (null), name);
}
return cname;
}
void process_ccode_attribute (Attribute a) {
foreach (NamedArgument arg in a.args) {
- if (arg.name.collate ("cname") == 0) {
+ if (arg.name == "cname") {
/* this will already be checked during semantic analysis */
if (arg.argument is LiteralExpression) {
var lit = ((LiteralExpression) arg.argument).literal;
public void process_attributes () {
foreach (Attribute a in attributes) {
- if (a.name.collate ("CCode") == 0) {
+ if (a.name == "CCode") {
process_ccode_attribute (a);
}
}
--- /dev/null
+/* valainterface.vala
+ *
+ * Copyright (C) 2006 Jürg Billeter
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Author:
+ * Jürg Billeter <j@bitron.ch>
+ */
+
+using GLib;
+
+namespace Vala {
+ public class Interface : Type_ {
+ List<string> type_parameters;
+ public List<TypeReference> base_types;
+
+ List<Method> methods;
+ List<Property> properties;
+
+ public static ref Interface new (string name, SourceReference source) {
+ return (new Interface (name = name, source_reference = source));
+ }
+
+ public void add_type_parameter (TypeParameter p) {
+ type_parameters.append (p);
+ p.type = this;
+ }
+
+ public void add_base_type (TypeReference type) {
+ base_types.append (type);
+ }
+
+ public void add_method (Method m) {
+ return_if_fail (m.instance && m.is_abstract && !m.is_virtual && !m.is_override);
+
+ methods.append (m);
+ }
+
+ public ref List<Method> get_methods () {
+ return methods.copy ();
+ }
+
+ public void add_property (Property prop) {
+ properties.append (prop);
+ }
+
+ public ref List<Property> get_properties () {
+ return properties.copy ();
+ }
+
+ private string cname;
+ private string lower_case_csuffix;
+
+ public override string get_cname () {
+ if (cname == null) {
+ cname = "%s%s".printf (@namespace.get_cprefix (), name);
+ }
+ return cname;
+ }
+
+ public string get_lower_case_csuffix () {
+ if (lower_case_csuffix == null) {
+ lower_case_csuffix = Namespace.camel_case_to_lower_case (name);
+ }
+ return lower_case_csuffix;
+ }
+
+ public void set_lower_case_csuffix (string csuffix) {
+ this.lower_case_csuffix = csuffix;
+ }
+
+ public override ref string get_lower_case_cname (string infix) {
+ if (infix == null) {
+ infix = "";
+ }
+ return "%s%s%s".printf (@namespace.get_lower_case_cprefix (), infix, get_lower_case_csuffix ());
+ }
+
+ public override ref string get_upper_case_cname (string infix) {
+ return get_lower_case_cname (infix).up (-1);
+ }
+
+ public override void accept (CodeVisitor visitor) {
+ visitor.visit_begin_interface (this);
+
+ foreach (TypeReference type in base_types) {
+ type.accept (visitor);
+ }
+
+ foreach (TypeParameter p in type_parameters) {
+ p.accept (visitor);
+ }
+
+ foreach (Method m in methods) {
+ m.accept (visitor);
+ }
+
+ foreach (Property prop in properties) {
+ prop.accept (visitor);
+ }
+
+ visitor.visit_end_interface (this);
+ }
+
+ public override bool is_reference_type () {
+ return true;
+ }
+ }
+}
}
private void write_identifier (string s) {
- if (s.collate ("namespace") == 0) {
+ if (s == "namespace") {
stream.putc ('@');
}
write_string (s);
return (new InvocationExpression (call = call, argument_list = argument_list, source_reference = source));
}
+ public void add_argument (Expression arg) {
+ _argument_list.append (arg);
+ }
+
public override void accept (CodeVisitor visitor) {
call.accept (visitor);
foreach (Expression expr in argument_list) {
public string get_cname () {
if (cname == null) {
var parent = symbol.parent_symbol.node;
- if (parent is Struct) {
- cname = "%s_%s".printf (((Struct) parent).get_lower_case_cname (null), name);
+ if (parent is Type_) {
+ cname = "%s_%s".printf (((Type_) parent).get_lower_case_cname (null), name);
} else if (parent is Namespace) {
cname = "%s%s".printf (((Namespace) parent).get_lower_case_cprefix (), name);
} else {
void process_ccode_attribute (Attribute a) {
foreach (NamedArgument arg in a.args) {
- if (arg.name.collate ("cname") == 0) {
+ if (arg.name == "cname") {
/* this will already be checked during semantic analysis */
if (arg.argument is LiteralExpression) {
var lit = ((LiteralExpression) arg.argument).literal;
public void process_attributes () {
foreach (Attribute a in attributes) {
- if (a.name.collate ("CCode") == 0) {
+ if (a.name == "CCode") {
process_ccode_attribute (a);
- } else if (a.name.collate ("ReturnsModifiedPointer") == 0) {
+ } else if (a.name == "ReturnsModifiedPointer") {
returns_modified_pointer = true;
- } else if (a.name.collate ("InstanceLast") == 0) {
+ } else if (a.name == "InstanceLast") {
instance_last = true;
}
}
public SourceReference source_reference { get; construct; }
List<Class> classes;
+ List<Interface> interfaces;
List<Struct> structs;
List<Enum> enums;
List<Field> fields;
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;
cl.accept (visitor);
}
+ foreach (Interface iface in interfaces) {
+ iface.accept (visitor);
+ }
+
foreach (Struct st in structs) {
st.accept (visitor);
}
void process_ccode_attribute (Attribute a) {
foreach (NamedArgument arg in a.args) {
- if (arg.name.collate ("cprefix") == 0) {
+ if (arg.name == "cprefix") {
/* this will already be checked during semantic analysis */
if (arg.argument is LiteralExpression) {
var lit = ((LiteralExpression) arg.argument).literal;
set_cprefix (((StringLiteral) lit).eval ());
}
}
- } else if (arg.name.collate ("lower_case_cprefix") == 0) {
+ } 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;
set_lower_case_cprefix (((StringLiteral) lit).eval ());
}
}
- } else if (arg.name.collate ("cheader_filename") == 0) {
+ } 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;
public void process_attributes () {
foreach (Attribute a in attributes) {
- if (a.name.collate ("CCode") == 0) {
+ if (a.name == "CCode") {
process_ccode_attribute (a);
}
}
SourceFile current_source_file;
List<NamespaceReference> current_using_directives;
-
+
+ TypeReference bool_type;
+ TypeReference string_type;
+
public void analyze (CodeContext context) {
root_symbol = context.root;
+
+ bool_type = new TypeReference ();
+ bool_type.type = (Type_) root_symbol.lookup ("bool").node;
+
+ string_type = new TypeReference ();
+ string_type.type = (Type_) root_symbol.lookup ("string").node;
+
current_symbol = root_symbol;
context.accept (this);
}
var base_method = (Method) sym.node;
if (base_method.is_abstract || base_method.is_virtual) {
m.base_method = base_method;
- //break;
+ break;
}
}
}
if (stmt.type_reference.type != null) {
current_source_file.add_symbol_dependency (stmt.type_reference.type.symbol, SourceFileDependencyType.SOURCE);
}
+
+ var decl = new VariableDeclarator (name = stmt.variable_name);
+ decl.type_reference = stmt.type_reference;
- stmt.symbol = new Symbol (node = stmt.type_reference);
+ stmt.symbol = new Symbol (node = decl);
current_symbol.add (stmt.variable_name, stmt.symbol);
}
public override void visit_boolean_literal (BooleanLiteral expr) {
- expr.static_type = new TypeReference ();
- expr.static_type.type = (Type_) root_symbol.lookup ("bool").node;
+ expr.static_type = bool_type;
}
public override void visit_character_literal (CharacterLiteral expr) {
}
public override void visit_string_literal (StringLiteral expr) {
- expr.static_type = new TypeReference ();
- expr.static_type.type = (Type_) root_symbol.lookup ("string").node;
+ expr.static_type = string_type;
}
public override void visit_null_literal (NullLiteral expr) {
+ /* empty TypeReference represents null */
+
expr.static_type = new TypeReference ();
}
}
public override void visit_member_access (MemberAccess expr) {
+ if (expr.inner.static_type == null
+ && expr.inner.symbol_reference == null) {
+ /* if there was an error in the inner expression, skip this check */
+ return;
+ }
+
if (expr.inner.static_type == null) {
if (expr.inner.symbol_reference.node is Namespace || expr.inner.symbol_reference.node is Type_) {
expr.symbol_reference = expr.inner.symbol_reference.lookup (expr.member_name);
if (expr.inner.static_type == null) {
Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, expr.inner.symbol_reference.get_full_name ()));
} else {
- Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, expr.inner.static_type.type.symbol.get_full_name ()));
+ Report.error (expr.source_reference, "The name `%s' does not exist in the context of `%s'".printf (expr.member_name, expr.inner.static_type.to_string ()));
}
return;
}
return true;
}
- /* int may be implicitly casted to long */
+ /* char may be implicitly casted to unichar */
if (expression_type.type == root_symbol.lookup ("char").node && expected_type.type == root_symbol.lookup ("unichar").node) {
return true;
}
}
public override void visit_invocation_expression (InvocationExpression expr) {
+ if (expr.call.symbol_reference == null) {
+ /* if method resolving didn't succeed, skip this check */
+ return;
+ }
+
var m = (Method) expr.call.symbol_reference.node;
expr.static_type = m.return_type;
}
var arg = (Expression) arg_it.data;
- if (!is_type_compatible (arg.static_type, param.type_reference)) {
- Report.warning (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.type.symbol.get_full_name (), param.type_reference.type.symbol.get_full_name ()));
+ if (arg.static_type != null && !is_type_compatible (arg.static_type, param.type_reference)) {
+ /* if there was an error in the argument,
+ * i.e. arg.static_type == null, skip type check */
+ Report.error (expr.source_reference, "Argument %d: Cannot convert from `%s' to `%s'".printf (i + 1, arg.static_type.type.symbol.get_full_name (), param.type_reference.to_string ()));
return;
}
}
if (!ellipsis && arg_it != null) {
- Report.warning (expr.source_reference, "Method `%s' does not take %d arguments".printf (m.symbol.get_full_name (), expr.argument_list.length ()));
+ Report.error (expr.source_reference, "Method `%s' does not take %d arguments".printf (m.symbol.get_full_name (), expr.argument_list.length ()));
return;
}
}
public override void visit_object_creation_expression (ObjectCreationExpression expr) {
+ if (expr.type_reference.type == null) {
+ /* if type resolving didn't succeed, skip this check */
+ return;
+ }
+
current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE);
expr.static_type = expr.type_reference;
}
public override void visit_unary_expression (UnaryExpression expr) {
- expr.static_type = expr.inner.static_type;
+ if (expr.inner.static_type == null) {
+ /* if there was an error in the inner expression, skip type check */
+ return;
+ }
+
+ if (expr.operator == UnaryOperator.PLUS || expr.operator == UnaryOperator.MINUS) {
+ // integer or floating point type
+
+ expr.static_type = expr.inner.static_type;
+ } else if (expr.operator == UnaryOperator.LOGICAL_NEGATION) {
+ // boolean type
+
+ expr.static_type = expr.inner.static_type;
+ } else if (expr.operator == UnaryOperator.BITWISE_COMPLEMENT) {
+ // integer type
+
+ expr.static_type = expr.inner.static_type;
+ } else if (expr.operator == UnaryOperator.REF) {
+ // value type
+
+ expr.static_type = expr.inner.static_type;
+ } else if (expr.operator == UnaryOperator.OUT) {
+ // reference type
+
+ expr.static_type = expr.inner.static_type;
+ } else {
+ assert_not_reached ();
+ }
}
public override void visit_cast_expression (CastExpression expr) {
+ if (expr.type_reference.type == null) {
+ /* if type resolving didn't succeed, skip this check */
+ return;
+ }
+
current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE);
expr.static_type = expr.type_reference;
}
-
+
+ private bool check_binary_type (BinaryExpression expr, string operation) {
+ if (!is_type_compatible (expr.right.static_type, expr.left.static_type)) {
+ Report.error (expr.source_reference, "%s: Cannot convert from `%s' to `%s'".printf (operation, expr.right.static_type.to_string (), expr.left.static_type.to_string ()));
+ return false;
+ }
+
+ return true;
+ }
+
public override void visit_binary_expression (BinaryExpression expr) {
- expr.static_type = expr.left.static_type;
+ if (expr.left.static_type == null
+ || expr.right.static_type == null) {
+ /* if there were any errors in inner expressions, skip type check */
+ return;
+ }
+
+ if (expr.left.static_type.type == string_type.type
+ && expr.operator == BinaryOperator.PLUS) {
+ if (expr.right.static_type.type != string_type.type) {
+ Report.error (expr.source_reference, "Operands must be strings");
+ }
+
+ expr.static_type = string_type;
+ } else if (expr.operator == BinaryOperator.PLUS
+ || expr.operator == BinaryOperator.MINUS
+ || expr.operator == BinaryOperator.MUL
+ || expr.operator == BinaryOperator.DIV) {
+ // TODO: check for integer or floating point type in expr.left
+
+ if (!check_binary_type (expr, "Arithmetic operation")) {
+ return;
+ }
+
+ expr.static_type = expr.left.static_type;
+ } else if (expr.operator == BinaryOperator.MOD
+ || expr.operator == BinaryOperator.SHIFT_LEFT
+ || expr.operator == BinaryOperator.SHIFT_RIGHT
+ || expr.operator == BinaryOperator.BITWISE_XOR) {
+ // TODO: check for integer type in expr.left
+
+ if (!check_binary_type (expr, "Arithmetic operation")) {
+ return;
+ }
+
+ expr.static_type = expr.left.static_type;
+ } else if (expr.operator == BinaryOperator.LESS_THAN
+ || expr.operator == BinaryOperator.GREATER_THAN
+ || expr.operator == BinaryOperator.LESS_THAN_OR_EQUAL
+ || expr.operator == BinaryOperator.GREATER_THAN_OR_EQUAL) {
+ if (expr.left.static_type.type == string_type.type
+ && expr.right.static_type.type == string_type.type) {
+ /* string comparison: convert to a.collate (b) OP 0 */
+
+ var cmp_call = new InvocationExpression (call = new MemberAccess (inner = expr.left, member_name = "collate"));
+ cmp_call.add_argument (expr.right);
+ expr.left = cmp_call;
+
+ expr.right = new LiteralExpression (literal = new IntegerLiteral (value = "0"));
+
+ expr.left.accept (this);
+ } else {
+ /* TODO: check for integer or floating point type in expr.left */
+
+ if (!check_binary_type (expr, "Relational operation")) {
+ return;
+ }
+ }
+
+ expr.static_type = bool_type;
+ } else if (expr.operator == BinaryOperator.EQUALITY
+ || expr.operator == BinaryOperator.INEQUALITY) {
+ /* relational operation */
+
+ if (!check_binary_type (expr, "Equality operation")) {
+ return;
+ }
+
+ if (expr.left.static_type.type == string_type.type
+ && expr.right.static_type.type == string_type.type) {
+ /* string comparison: convert to a.collate (b) OP 0 */
+
+ var cmp_call = new InvocationExpression (call = new MemberAccess (inner = expr.left, member_name = "collate"));
+ cmp_call.add_argument (expr.right);
+ expr.left = cmp_call;
+
+ expr.right = new LiteralExpression (literal = new IntegerLiteral (value = "0"));
+
+ expr.left.accept (this);
+ }
+
+ expr.static_type = bool_type;
+ } else if (expr.operator == BinaryOperator.BITWISE_AND
+ || expr.operator == BinaryOperator.BITWISE_OR) {
+ // integer type or flags type
+
+ expr.static_type = expr.left.static_type;
+ } else if (expr.operator == BinaryOperator.AND
+ || expr.operator == BinaryOperator.OR) {
+ if (expr.left.static_type.type != bool_type.type || expr.right.static_type.type != bool_type.type) {
+ Report.error (expr.source_reference, "Operands must be boolean");
+ }
+
+ expr.static_type = bool_type;
+ } else {
+ assert_not_reached ();
+ }
}
public override void visit_type_check (TypeCheck expr) {
+ if (expr.type_reference.type == null) {
+ /* if type resolving didn't succeed, skip this check */
+ return;
+ }
+
current_source_file.add_symbol_dependency (expr.type_reference.type.symbol, SourceFileDependencyType.SOURCE);
- expr.static_type = new TypeReference ();
- expr.static_type.type = (Type_) root_symbol.lookup ("bool").node;
+ expr.static_type = bool_type;
}
}
}
public string get_cheader_filename () {
if (cheader_filename == null) {
- var basename = filename.ndup (filename.len (-1) - ".vala".len (-1));
+ var basename = filename.ndup ((uint) (filename.len (-1) - ".vala".len (-1)));
cheader_filename = "%s.h".printf (basename);
}
return cheader_filename;
public string get_csource_filename () {
if (csource_filename == null) {
- var basename = filename.ndup (filename.len (-1) - ".vala".len (-1));
+ var basename = filename.ndup ((uint) (filename.len (-1) - ".vala".len (-1)));
csource_filename = "%s.c".printf (basename);
}
return csource_filename;
public ref string eval () {
/* remove quotes */
- var noquotes = value.offset (1).ndup (value.len (-1) - 2);
+ var noquotes = value.offset (1).ndup ((uint) (value.len (-1) - 2));
/* unescape string */
return noquotes.compress ();
}
public string cname;
public string lower_case_csuffix;
bool reference_type;
- public bool has_private_fields;
public static ref Struct new (string name, SourceReference source) {
return (new Struct (name = name, source_reference = source));
public void add_field (Field f) {
fields.append (f);
- if (f.access == MemberAccessibility.PRIVATE) {
- has_private_fields = true;
- }
}
public ref List<Field> get_fields () {
public override void accept (CodeVisitor visitor) {
visitor.visit_begin_struct (this);
- visit_children (visitor);
-
- visitor.visit_end_struct (this);
- }
-
- public void visit_children (CodeVisitor visitor) {
foreach (TypeParameter p in type_parameters) {
p.accept (visitor);
}
foreach (Method m in methods) {
m.accept (visitor);
}
+
+ visitor.visit_end_struct (this);
}
public override string get_cname () {
this.lower_case_csuffix = csuffix;
}
- public ref string get_lower_case_cname (string infix) {
+ public override ref string get_lower_case_cname (string infix) {
if (infix == null) {
infix = "";
}
void process_ccode_attribute (Attribute a) {
foreach (NamedArgument arg in a.args) {
- if (arg.name.collate ("cname") == 0) {
+ if (arg.name == "cname") {
/* this will already be checked during semantic analysis */
if (arg.argument is LiteralExpression) {
var lit = ((LiteralExpression) arg.argument).literal;
set_cname (((StringLiteral) lit).eval ());
}
}
- } else if (arg.name.collate ("cheader_filename") == 0) {
+ } 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;
public void process_attributes () {
foreach (Attribute a in attributes) {
- if (a.name.collate ("CCode") == 0) {
+ if (a.name == "CCode") {
process_ccode_attribute (a);
- } else if (a.name.collate ("ReferenceType") == 0) {
+ } else if (a.name == "ReferenceType") {
reference_type = true;
}
}
public override void visit_begin_class (Class cl) {
if (cl.@namespace.symbol.lookup (cl.name) != null) {
+ cl.error = true;
Report.error (cl.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (cl.@namespace.symbol.get_full_name (), cl.name));
return;
}
}
public override void visit_end_class (Class cl) {
+ if (cl.error) {
+ /* skip classes with errors */
+ return;
+ }
+
current_symbol = current_symbol.parent_symbol;
}
public override void visit_begin_struct (Struct st) {
if (st.@namespace.symbol.lookup (st.name) != null) {
+ st.error = true;
Report.error (st.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (st.@namespace.symbol.get_full_name (), st.name));
return;
}
}
public override void visit_end_struct (Struct st) {
+ if (st.error) {
+ /* skip structs with errors */
+ return;
+ }
+
+ current_symbol = current_symbol.parent_symbol;
+ }
+
+ public override void visit_begin_interface (Interface iface) {
+ if (iface.@namespace.symbol.lookup (iface.name) != null) {
+ iface.error = true;
+ Report.error (iface.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (iface.@namespace.symbol.get_full_name (), iface.name));
+ return;
+ }
+ iface.symbol = new Symbol (node = iface);
+ iface.@namespace.symbol.add (iface.name, iface.symbol);
+
+ current_symbol = iface.symbol;
+ }
+
+ public override void visit_end_interface (Interface iface) {
+ if (iface.error) {
+ /* skip interfaces with errors */
+ return;
+ }
+
current_symbol = current_symbol.parent_symbol;
}
public override void visit_begin_enum (Enum en) {
if (en.@namespace.symbol.lookup (en.name) != null) {
+ en.error = true;
Report.error (en.source_reference, "The namespace `%s' already contains a definition for `%s'".printf (en.@namespace.symbol.get_full_name (), en.name));
return;
}
}
public override void visit_end_enum (Enum en) {
+ if (en.error) {
+ /* skip enums with errors */
+ return;
+ }
+
current_symbol = current_symbol.parent_symbol;
}
public override void visit_constant (Constant c) {
if (current_symbol.lookup (c.name) != null) {
+ c.error = true;
Report.error (c.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), c.name));
return;
}
public override void visit_field (Field f) {
if (current_symbol.lookup (f.name) != null) {
+ f.error = true;
Report.error (f.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), f.name));
return;
}
public override void visit_begin_method (Method m) {
if (current_symbol.lookup (m.name) != null) {
+ m.error = true;
Report.error (m.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), m.name));
return;
}
current_symbol = m.symbol;
if (m.instance) {
- var type = new TypeReference ();
- type.type = (Type_) m.symbol.parent_symbol.node;
- current_symbol.add ("this", new Symbol (node = type));
+ var decl = new FormalParameter (name = "this", type_reference = new TypeReference ());
+ decl.type_reference.type = (Type_) m.symbol.parent_symbol.node;
+ current_symbol.add (decl.name, new Symbol (node = decl));
}
}
public override void visit_end_method (Method m) {
+ if (m.error) {
+ /* skip methods with errors */
+ return;
+ }
+
current_symbol = current_symbol.parent_symbol;
}
public override void visit_begin_property (Property prop) {
if (current_symbol.lookup (prop.name) != null) {
+ prop.error = true;
Report.error (prop.source_reference, "The type `%s' already contains a definition for `%s'".printf (current_symbol.get_full_name (), prop.name));
return;
}
current_symbol.add (prop.name, prop.symbol);
current_symbol = prop.symbol;
- var type = new TypeReference ();
- type.type = (Type_) prop.symbol.parent_symbol.node;
- current_symbol.add ("this", new Symbol (node = type));
+ var decl = new FormalParameter (name = "this", type_reference = new TypeReference ());
+ decl.type_reference.type = (Type_) prop.symbol.parent_symbol.node;
+ current_symbol.add (decl.name, new Symbol (node = decl));
}
public override void visit_end_property (Property prop) {
+ if (prop.error) {
+ /* skip properties with errors */
+ return;
+ }
+
current_symbol = current_symbol.parent_symbol;
}
current_symbol = acc.symbol;
if (acc.writable || acc.construct_) {
- current_symbol.add ("value", new Symbol (node = ((Property) current_symbol.parent_symbol.node).type_reference));
+ var decl = new VariableDeclarator (name = "value");
+ decl.type_reference = ((Property) current_symbol.parent_symbol.node).type_reference;
+
+ current_symbol.add ("value", new Symbol (node = decl));
}
if (acc.body == null) {
cl.base_class = type.type;
}
}
- if (cl.base_class == null && (cl.name.collate ("Object") != 0 || cl.@namespace.name.collate ("GLib") != 0)) {
+ if (cl.base_class == null && (cl.name != "Object" || cl.@namespace.name != "GLib")) {
cl.base_class = (Class) root_symbol.lookup ("GLib").lookup ("Object").node;
}
}
public override void visit_type_reference (TypeReference type) {
- if (type.type_name.collate ("void") == 0) {
+ if (type.type_name == "void") {
return;
}
public abstract string get_cname ();
public abstract bool is_reference_type ();
public abstract string get_upper_case_cname (string infix);
+ public abstract string get_lower_case_cname (string infix);
public List<string> cheader_filenames;
public ref List<string> get_cheader_filenames () {
public ref string get_upper_case_cname (string infix) {
return type.get_upper_case_cname (infix);
}
+
+ public string to_string () {
+ if (type != null) {
+ return type.symbol.get_full_name ();
+ } else if (type_parameter != null) {
+ return type_parameter.name;
+ } else {
+ return "null";
+ }
+ }
}
}
[CCode (cname = "g_strconcat")]
public ref string concat (string string2, ...);
[CCode (cname = "g_strndup")]
- public ref string ndup (int n);
+ public ref string ndup (uint n); /* FIXME: only UTF-8 */
[CCode (cname = "g_strcompress")]
public ref string compress ();
[CCode (cname = "g_strsplit")]
[CCode (cname = "g_utf8_prev_char")]
public string prev_char ();
[CCode (cname = "g_utf8_strlen")]
- public long len (long max /*= -1*/);
+ public long len (int max /*= -1*/);
[CCode (cname = "g_utf8_strchr")]
- public string chr (long len, unichar c);
+ public string chr (int len, unichar c);
[CCode (cname = "g_utf8_strup")]
- public ref string up (long len /*= -1*/);
+ public ref string up (int len /*= -1*/);
[CCode (cname = "g_utf8_collate")]
public int collate (string str2);
}
public struct Error {
}
+ public static void assert_not_reached ();
public static void return_if_fail (bool expr);
public enum FileTest {