+2008-01-09 Jürg Billeter <j@bitron.ch>
+
+ * vala/parser.y, vala/scanner.l, vala/valaclass.vala,
+ vala/valacodecontext.vala, vala/valadatatype.vala,
+ vala/valainterface.vala, vala/valanulltype.vala,
+ vala/valasemanticanalyzer.vala, vala/valasymbolresolver.vala,
+ vala/valaunresolvedtype.vala, gobject/valaccodegenerator.vala,
+ gobject/valaccodegeneratorinvocationexpression.vala,
+ gobject/valaccodegeneratormethod.vala, compiler/valacompiler.vala:
+
+ Use non-null types by default when passing --enable-non-null to valac,
+ `?´ marks nullable types, deprecate `!´ to mark non-null types,
+ fixes bug 504222
+
2008-01-08 Jürg Billeter <j@bitron.ch>
* gobject/valaccodegenerator.vala: fix memory management with simple
/* valacompiler.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter
+ * Copyright (C) 2006-2008 Jürg Billeter
* Copyright (C) 1996-2002, 2004, 2005, 2006 Free Software Foundation, Inc.
*
* This library is free software; you can redistribute it and/or
static int optlevel;
static bool disable_assert;
static bool disable_checking;
+ static bool non_null;
static string cc_command;
[NoArrayLength]
static string[] cc_options;
{ "optimize", 'O', 0, OptionArg.INT, ref optlevel, "Optimization level", "OPTLEVEL" },
{ "disable-assert", 0, 0, OptionArg.NONE, ref disable_assert, "Disable assertions", null },
{ "disable-checking", 0, 0, OptionArg.NONE, ref disable_checking, "Disable run-time checks", null },
+ { "enable-non-null", 0, 0, OptionArg.NONE, ref non_null, "Enable non-null types", null },
{ "cc", 0, 0, OptionArg.STRING, out cc_command, "Use COMMAND as C compiler command", "COMMAND" },
{ "Xcc", 'X', 0, OptionArg.STRING_ARRAY, out cc_options, "Pass OPTION to the C compiler", "OPTION..." },
{ "save-temps", 0, 0, OptionArg.NONE, out save_temps, "Keep temporary files", null },
context.library = library;
context.assert = !disable_assert;
context.checking = !disable_checking;
+ context.non_null = non_null;
context.ccode_only = ccode_only;
context.compile_only = compile_only;
var cassign = new CCodeAssignment (cvar, ccomma);
// g_free (NULL) is allowed
- if (type.non_null || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) {
+ if ((context.non_null && !type.nullable) || (type.data_type != null && !type.data_type.is_reference_counting () && type.data_type.get_free_function () == "g_free")) {
return new CCodeParenthesizedExpression (cassign);
}
var ccall = new CCodeFunctionCall (dupexpr);
- if (expr.static_type.non_null && expr.static_type.type_parameter == null) {
+ if ((context.non_null && !expr.static_type.nullable) && expr.static_type.type_parameter == null) {
ccall.add_argument ((CCodeExpression) expr.ccodenode);
return ccall;
/* valaccodegeneratorinvocationexpression.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
cexpr = get_implicit_cast_expression (cexpr, arg.static_type, param.type_reference);
// pass non-simple struct instances always by reference
- if (param.type_reference.data_type is Struct && !((Struct) param.type_reference.data_type).is_simple_type ()) {
+ if (!(arg.static_type is NullType) && param.type_reference.data_type is Struct && !((Struct) param.type_reference.data_type).is_simple_type ()) {
// we already use a reference for arguments of ref and out parameters
if (!param.type_reference.is_ref && !param.type_reference.is_out) {
cexpr = new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, cexpr);
var t = param.type_reference.data_type;
if (t != null && t.is_reference_type () && !param.type_reference.is_out) {
- var type_check = create_method_type_check_statement (m, creturn_type, t, param.type_reference.non_null, param.name);
+ var type_check = create_method_type_check_statement (m, creturn_type, t, (context.non_null && !param.type_reference.nullable), param.name);
if (type_check != null) {
type_check.line = function.line;
cinit.append (type_check);
/* parser.y
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
%token SEMICOLON ";"
%token HASH "#"
%token INTERR "?"
+%token NULLABLE_INTERR "nullable ?"
%token ASSIGN_BITWISE_OR "|="
%token ASSIGN_BITWISE_AND "&="
%type <local_variable_declaration> local_variable_declaration
%type <type_reference> local_variable_type
%type <num> opt_op_neg
+%type <num> opt_any_interr
+%type <num> opt_nullable_interr
%type <statement> expression_statement
%type <expression> statement_expression
%type <statement> selection_statement
;
type
- : type_name opt_rank_specifier opt_op_neg
+ : type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $1;
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2);
- if ($3) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($4) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
- | WEAK type_name opt_rank_specifier opt_op_neg
+ | WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $2;
vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
- if ($4) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($5) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
- | type_name opt_rank_specifier opt_op_neg HASH
+ | type_name opt_rank_specifier opt_op_neg opt_any_interr HASH
{
$$ = $1;
vala_unresolved_type_set_transfers_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2);
- if ($3) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($4) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
- | REF type_name opt_rank_specifier opt_op_neg
+ | REF type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $2;
vala_unresolved_type_set_is_ref (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
- if ($4) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($5) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
- | OUT type_name opt_rank_specifier opt_op_neg
+ | OUT type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $2;
vala_unresolved_type_set_is_out (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
- if ($4) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($5) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
- | OUT WEAK type_name opt_rank_specifier opt_op_neg
+ | OUT WEAK type_name opt_rank_specifier opt_op_neg opt_any_interr
{
$$ = $3;
vala_unresolved_type_set_is_weak (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_is_out (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $4);
- if ($5) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($6) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
- | type_name stars opt_rank_specifier opt_op_neg
+ | type_name stars opt_rank_specifier
{
$$ = $1;
vala_unresolved_type_set_pointer_level (VALA_UNRESOLVED_TYPE ($$), $2);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
- if ($4) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
- }
}
| VOID
{
g_object_unref ($3);
}
}
- | relational_expression IS type
+ | relational_expression IS type_name
{
if ($1 == NULL || $3 == NULL) {
// error in subexpression
g_object_unref ($3);
}
}
- | relational_expression AS type
+ | relational_expression AS type_name
{
if ($1 == NULL || $3 == NULL) {
// error in subexpression
/* don't use type to prevent reduce/reduce conflict */
local_variable_type
- : primary_expression opt_bracket_pair opt_op_neg
+ : primary_expression opt_bracket_pair opt_op_neg opt_nullable_interr
{
ValaSourceReference *src = src(@1);
$$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($1));
g_object_unref (src);
vala_unresolved_type_set_takes_ownership (VALA_UNRESOLVED_TYPE ($$), TRUE);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $2);
- if ($3) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($4) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
| primary_expression stars
g_object_unref (src);
vala_unresolved_type_set_pointer_level (VALA_UNRESOLVED_TYPE ($$), $2);
}
- | WEAK primary_expression opt_bracket_pair opt_op_neg
+ | WEAK primary_expression opt_bracket_pair opt_op_neg opt_nullable_interr
{
ValaSourceReference *src = src(@2);
$$ = VALA_DATA_TYPE (vala_unresolved_type_new_from_expression ($2));
g_object_unref ($2);
g_object_unref (src);
vala_unresolved_type_set_array_rank (VALA_UNRESOLVED_TYPE ($$), $3);
- if ($4) {
- vala_unresolved_type_set_non_null (VALA_UNRESOLVED_TYPE ($$), TRUE);
+ if ($5) {
+ vala_unresolved_type_set_nullable (VALA_UNRESOLVED_TYPE ($$), TRUE);
}
}
| VOID
}
;
+opt_any_interr
+ : /* empty */
+ {
+ $$ = FALSE;
+ }
+ | INTERR
+ {
+ $$ = TRUE;
+ }
+ | NULLABLE_INTERR
+ {
+ $$ = TRUE;
+ }
+ ;
+
+opt_nullable_interr
+ : /* empty */
+ {
+ $$ = FALSE;
+ }
+ | NULLABLE_INTERR
+ {
+ $$ = TRUE;
+ }
+ ;
+
expression_statement
: comment statement_expression SEMICOLON
{
/* scanner.l
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
"," { uploc; return COMMA; }
";" { uploc; return SEMICOLON; }
"#" { uploc; return HASH; }
+"?"{space}({ident}("="|";")|"[") { yyless (1); uploc; return NULLABLE_INTERR; }
"?" { uploc; return INTERR; }
"|=" { uploc; return ASSIGN_BITWISE_OR; }
/* valaclass.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter
+ * Copyright (C) 2006-2008 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
* @param f a field
*/
public void add_field (Field! f) {
- if (f.type_reference is UnresolvedType) {
- // non_null fields not yet supported due to initialization issues
- ((UnresolvedType) f.type_reference).non_null = false;
- }
fields.add (f);
if (f.access == SymbolAccessibility.PRIVATE && f.instance) {
_has_private_fields = true;
source_reference != null && !source_reference.file.pkg) {
/* automatic property accessor body generation */
var field_type = prop.type_reference.copy ();
- // non_null fields not yet supported due to initialization issues
- ((UnresolvedType) field_type).non_null = false;
var f = new Field ("_%s".printf (prop.name), field_type, null, prop.source_reference);
f.access = SymbolAccessibility.PRIVATE;
add_field (f);
/* valacodecontext.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter
+ * Copyright (C) 2006-2008 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
public bool checking { get; set; }
/**
+ * Enable non-null types.
+ */
+ public bool non_null {
+ get { return _non_null; }
+ set { _non_null = value; }
+ }
+
+ /**
* Output C code, don't compile to object code.
*/
public bool ccode_only { get; set; }
private Gee.List<string> packages = new ArrayList<string> (str_equal);
+ private static bool _non_null = false;
+
/**
* The root namespace of the symbol tree.
*
codegen = new CodeGenerator ();
}
+ public static bool is_non_null_enabled () {
+ return _non_null;
+ }
+
/**
* Returns a copy of the list of source files.
*
/* valadatatype.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Specifies that the expression is a reference used in out parameters.
*/
public bool is_out { get; set; }
-
+
/**
- * Specifies that the expression is guaranteed not to be null.
+ * Specifies that the expression may be null.
*/
- public bool non_null { get; set; }
-
+ public bool nullable { get; set; }
+
/**
* Specifies that the expression is known to be null.
*/
}
s += ">";
}
- if (non_null) {
- s += "!";
+ if (nullable) {
+ s += "?";
}
return s;
result.transfers_ownership = transfers_ownership;
result.takes_ownership = takes_ownership;
result.is_out = is_out;
- result.non_null = non_null;
+ result.nullable = nullable;
result.data_type = data_type;
result.type_parameter = type_parameter;
result.floating_reference = floating_reference;
if (type2.is_out != is_out) {
return false;
}
- if (type2.non_null != non_null) {
+ if (type2.nullable != nullable) {
return false;
}
if (type2.data_type != data_type) {
return false;
}
- if (type2.non_null && !non_null) {
+ if (!type2.nullable && nullable) {
return false;
}
return (data_type == null && type_parameter == null);
}
- if (data_type == null) {
- /* null can be cast to any reference or array type or pointer type */
- if (target_type.type_parameter != null ||
- target_type is PointerType ||
- target_type.data_type.is_reference_type () ||
- target_type.is_out ||
- target_type.data_type is Array ||
- target_type.data_type is Callback ||
- target_type.data_type.get_attribute ("PointerType") != null) {
- return true;
- }
-
- /* null is not compatible with any other type (i.e. value types) */
- return false;
- }
-
if (target_type is PointerType || (target_type.data_type != null && target_type.data_type.get_attribute ("PointerType") != null)) {
/* any reference or array type or pointer type can be cast to a generic pointer */
if (type_parameter != null ||
/* valainterface.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter
+ * Copyright (C) 2006-2008 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
* @param f a field
*/
public void add_field (Field! f) {
- // non_null fields not yet supported due to initialization issues
- f.type_reference.non_null = false;
fields.add (f);
scope.add (f.name, f);
}
/* valanulltype.vala
*
- * Copyright (C) 2007 Jürg Billeter
+ * Copyright (C) 2007-2008 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
/* null can be cast to any reference or array type or pointer type */
if (target_type.type_parameter != null ||
target_type is PointerType ||
- target_type.data_type.is_reference_type () ||
target_type.is_out ||
- target_type.data_type is Array ||
- target_type.data_type is Callback ||
+ target_type.nullable ||
target_type.data_type.get_attribute ("PointerType") != null) {
return true;
}
+ if (target_type.data_type.is_reference_type () ||
+ target_type.data_type is Array ||
+ target_type.data_type is Callback) {
+ return !(CodeContext.is_non_null_enabled ());
+ }
+
/* null is not compatible with any other type (i.e. value types) */
return false;
}
/* valasemanticanalyzer.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
public override void visit_string_literal (StringLiteral! expr) {
expr.static_type = string_type.copy ();
- expr.static_type.non_null = true;
}
public override void visit_null_literal (NullLiteral! expr) {
base_type = new DataType ();
base_type.data_type = type.data_type;
base_type.type_parameter = type.type_parameter;
- base_type.non_null = type.non_null;
+ base_type.nullable = type.nullable;
base_type.is_null = type.is_null;
base_type.transfers_ownership = type.transfers_ownership;
} else {
break;
}
}
- base_type.non_null = base_type.non_null && type.non_null;
+ base_type.nullable = base_type.nullable || type.nullable;
base_type.is_null = base_type.is_null && type.is_null;
// if one subexpression transfers ownership, all subexpressions must transfer ownership
// FIXME add ref calls to subexpressions that don't transfer ownership
/* valasymbolresolver.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
type.transfers_ownership = unresolved_type.transfers_ownership;
type.is_ref = unresolved_type.is_ref;
type.is_out = unresolved_type.is_out;
- type.non_null = unresolved_type.non_null;
+ type.nullable = unresolved_type.nullable;
foreach (DataType type_arg in unresolved_type.get_type_arguments ()) {
type.add_type_argument (type_arg);
}
/* valaunresolvedtype.vala
*
- * Copyright (C) 2006-2007 Jürg Billeter, Raffaele Sandrini
+ * Copyright (C) 2006-2008 Jürg Billeter, Raffaele Sandrini
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* Specifies that the expression is a reference used in out parameters.
*/
public bool is_out { get; set; }
-
+
/**
- * Specifies that the expression is guaranteed not to be null.
+ * Specifies that the expression may be null.
*/
- public bool non_null { get; set; }
+ public bool nullable { get; set; }
public UnresolvedType () {
}
result.transfers_ownership = transfers_ownership;
result.takes_ownership = takes_ownership;
result.is_out = is_out;
- result.non_null = non_null;
+ result.nullable = nullable;
result.namespace_name = namespace_name;
result.type_name = type_name;
result.array_rank = array_rank;