2006-09-02 Jürg Billeter <j@bitron.ch>
+ * vala/valasemanticanalyzer.vala: use IntegerType, FloatingType, and
+ rank attributes to analyze arithmetic operations
+ * vala/valacodegenerator.vala: generate C casts for explicit value-type
+ casts
+ * vala/valastruct.vala: add is_integer_type, is_floating_type, and
+ get_rank methods, add IntegerType and FloatingType attributes
+ * vala/valasemanticanalyzer.vala, vala/valacastexpression.vala,
+ vala/valainstancecast.vala, ccode/valaccodecastexpression.vala: fix
+ typos
+ * vapi/glib-2.0.vala: add int16, uint16, int32, uint32, use IntegerType
+ and FloatingType attributes
+
+2006-09-02 Jürg Billeter <j@bitron.ch>
+
* vala/parser.y: set accessibility for constants
* vala/valasemanticanalyzer.vala: set return type in property set
accessors to void
*/
public class Vala.CCodeCastExpression : CCodeExpression {
/**
- * The expression to be casted.
+ * The expression to be cast.
*/
public CCodeExpression! inner { get; set construct; }
*/
public class Vala.CastExpression : Expression {
/**
- * The expression to be casted.
+ * The expression to be cast.
*/
public Expression! inner { get; set construct; }
/**
* Creates a new cast expression.
*
- * @param inner expression to be casted
+ * @param inner expression to be cast
* @param type target type
* @return newly created cast expression
*/
&& decl.initializer.static_type.data_type != null
&& decl.type_reference.data_type.is_reference_type ()
&& decl.initializer.static_type.data_type != decl.type_reference.data_type) {
+ // FIXME: use C cast if debugging disabled
rhs = new InstanceCast (rhs, decl.type_reference.data_type);
}
} else if (decl.type_reference.data_type != null && decl.type_reference.data_type.is_reference_type ()) {
if (f.instance) {
ref CCodeExpression typed_inst;
if (f.symbol.parent_symbol.node != base_type) {
+ // FIXME: use C cast if debugging disabled
typed_inst = new CCodeFunctionCall (new CCodeIdentifier (((DataType) f.symbol.parent_symbol.node).get_upper_case_cname (null)));
((CCodeFunctionCall) typed_inst).add_argument (pub_inst);
} else {
/* cast if necessary */
if (cl != base_type) {
+ // FIXME: use C cast if debugging disabled
var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccast.add_argument (pub_inst);
typed_pub_inst = ccast;
/* cast if necessary */
if (cl != base_type) {
+ // FIXME: use C cast if debugging disabled
var ccast = new CCodeFunctionCall (new CCodeIdentifier (cl.get_upper_case_cname (null)));
ccast.add_argument (pub_inst);
typed_pub_inst = ccast;
} else {
var ccall = new CCodeFunctionCall (new CCodeIdentifier ("g_signal_emit_by_name"));
+ // FIXME: use C cast if debugging disabled
var ccast = new CCodeFunctionCall (new CCodeIdentifier ("G_OBJECT"));
ccast.add_argument (pub_inst);
ccall.add_argument (ccast);
}
if (req_cast && ((DataType) m.symbol.parent_symbol.node).is_reference_type ()) {
+ // FIXME: use C cast if debugging disabled
var ccall = new CCodeFunctionCall (new CCodeIdentifier (((DataType) base_method.symbol.parent_symbol.node).get_upper_case_cname (null)));
ccall.add_argument (instance);
instance = ccall;
}
}
if (param.type_reference.data_type != arg.static_type.data_type) {
+ // FIXME: use C cast if debugging disabled
var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null)));
ccall.add_argument (cexpr);
cexpr = ccall;
&& param.type_reference.data_type.is_reference_type ()
&& arg.static_type.data_type != null
&& param.type_reference.data_type != arg.static_type.data_type) {
+ // FIXME: use C cast if debugging disabled
var ccall = new CCodeFunctionCall (new CCodeIdentifier (param.type_reference.data_type.get_upper_case_cname (null)));
ccall.add_argument (cexpr);
cexpr = ccall;
public override void visit_cast_expression (CastExpression! expr) {
if (expr.type_reference.data_type is Struct || expr.type_reference.data_type is Enum || expr.type_reference.data_type is Flags) {
- expr.ccodenode = expr.inner.ccodenode;
+ expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
} else {
+ // GObject cast
expr.ccodenode = new InstanceCast ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.data_type);
}
public DataType! type_reference { get; set construct; }
/**
- * The expression to be casted.
+ * The expression to be cast.
*/
public CCodeExpression! inner { get; set construct; }
return (expression_type.data_type == null && expected_type.type_parameter == null);
}
- /* null can be casted to any reference or array type */
+ /* null can be cast to any reference or array type */
if (expression_type.data_type == null &&
(expected_type.type_parameter != null ||
expected_type.data_type.is_reference_type () ||
return true;
}
- /* int may be implicitly casted to long */
- if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("long").node) {
- return true;
- }
-
- /* int may be implicitly casted to ulong */
- if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("ulong").node) {
- return true;
- }
-
- /* uint may be implicitly casted to long */
- if (expression_type.data_type == root_symbol.lookup ("uint").node && expected_type.data_type == root_symbol.lookup ("long").node) {
- return true;
- }
-
- /* uint may be implicitly casted to ulong */
- if (expression_type.data_type == root_symbol.lookup ("uint").node && expected_type.data_type == root_symbol.lookup ("ulong").node) {
- return true;
- }
-
- /* int may be implicitly casted to uint */
- if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("uint").node) {
- return true;
- }
-
- /* uint may be implicitly casted to int */
- if (expression_type.data_type == root_symbol.lookup ("uint").node && expected_type.data_type == root_symbol.lookup ("int").node) {
- return true;
- }
-
- /* long may be implicitly casted to ulong */
- if (expression_type.data_type == root_symbol.lookup ("long").node && expected_type.data_type == root_symbol.lookup ("ulong").node) {
- return true;
- }
-
- /* ulong may be implicitly casted to long */
- if (expression_type.data_type == root_symbol.lookup ("ulong").node && expected_type.data_type == root_symbol.lookup ("long").node) {
- return true;
- }
-
- /* int may be implicitly casted to double */
- if (expression_type.data_type == root_symbol.lookup ("int").node && expected_type.data_type == root_symbol.lookup ("double").node) {
- return true;
- }
-
- /* char may be implicitly casted to unichar */
- if (expression_type.data_type == root_symbol.lookup ("char").node && expected_type.data_type == root_symbol.lookup ("unichar").node) {
- return true;
+ if (expression_type.data_type is Struct && expected_type.data_type is Struct) {
+ var expr_struct = (Struct) expression_type.data_type;
+ var expect_struct = (Struct) expected_type.data_type;
+
+ /* integer types may be implicitly cast to floating point types */
+ if (expr_struct.is_integer_type () && expect_struct.is_floating_type ()) {
+ return true;
+ }
+
+ if ((expr_struct.is_integer_type () && expect_struct.is_integer_type ()) ||
+ (expr_struct.is_floating_type () && expect_struct.is_floating_type ())) {
+ if (expr_struct.get_rank () <= expect_struct.get_rank ()) {
+ return true;
+ }
+ }
}
return expression_type.data_type.is_subtype_of (expected_type.data_type);
/* if type resolving didn't succeed, skip this check */
return;
}
+
+ // FIXME: check whether cast is allowed
current_source_file.add_symbol_dependency (expr.type_reference.data_type.symbol, SourceFileDependencyType.SOURCE);
return true;
}
+ private ref TypeReference get_arithmetic_result_type (TypeReference! left_type, TypeReference! right_type) {
+ if (!(left_type.data_type is Struct) || !(right_type.data_type is Struct)) {
+ // at least one operand not struct
+ return null;
+ }
+
+ var left = (Struct) left_type.data_type;
+ var right = (Struct) right_type.data_type;
+
+ if ((!left.is_floating_type () && !left.is_integer_type ()) ||
+ (!right.is_floating_type () && !right.is_integer_type ())) {
+ // at least one operand not numeric
+ return null;
+ }
+
+ if (left.is_floating_type () == right.is_floating_type ()) {
+ // both operands integer or floating type
+ if (left.get_rank () >= right.get_rank ()) {
+ return left_type;
+ } else {
+ return right_type;
+ }
+ } else {
+ // one integer and one floating type operand
+ if (left.is_floating_type ()) {
+ return left_type;
+ } else {
+ return right_type;
+ }
+ }
+ }
+
public override void visit_binary_expression (BinaryExpression! expr) {
if (expr.left.error || expr.right.error) {
/* if there were any errors in inner expressions, skip type check */
|| expr.operator == BinaryOperator.MINUS
|| expr.operator == BinaryOperator.MUL
|| expr.operator == BinaryOperator.DIV) {
- // TODO: check for integer or floating point type in expr.left
+ expr.static_type = get_arithmetic_result_type (expr.left.static_type, expr.right.static_type);
- if (!check_binary_type (expr, "Arithmetic operation")) {
+ if (expr.static_type == null) {
expr.error = true;
+ Report.error (expr.source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (expr.left.static_type.to_string (), expr.right.static_type.to_string ()));
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
+ expr.static_type = get_arithmetic_result_type (expr.left.static_type, expr.right.static_type);
- if (!check_binary_type (expr, "Arithmetic operation")) {
+ if (expr.static_type == null) {
expr.error = true;
+ Report.error (expr.source_reference, "Arithmetic operation not supported for types `%s' and `%s'".printf (expr.left.static_type.to_string (), expr.right.static_type.to_string ()));
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
* Represents a struct declaration in the source code.
*/
public class Vala.Struct : DataType {
- List<TypeParameter> type_parameters;
- List<Constant> constants;
- List<Field> fields;
- List<Method> methods;
+ private List<TypeParameter> type_parameters;
+ private List<Constant> constants;
+ private List<Field> fields;
+ private List<Method> methods;
private List<TypeReference> base_types;
- string cname;
- string dup_function;
- string free_function;
- string type_id;
- string lower_case_cprefix;
- string lower_case_csuffix;
- bool reference_type;
- string marshaller_type_name;
+ private string cname;
+ private string dup_function;
+ private string free_function;
+ private string type_id;
+ private string lower_case_cprefix;
+ private string lower_case_csuffix;
+ private bool reference_type;
+ private bool integer_type;
+ private bool floating_type;
+ private int rank;
+ private string marshaller_type_name;
/**
* Specifies the default construction method.
}
/**
+ * Returns whether this is an integer type.
+ *
+ * @return true if this is an integer type, false otherwise
+ */
+ public bool is_integer_type () {
+ return integer_type;
+ }
+
+ /**
+ * Returns whether this is a floating point type.
+ *
+ * @return true if this is a floating point type, false otherwise
+ */
+ public bool is_floating_type () {
+ return floating_type;
+ }
+
+ /**
+ * Returns the rank of this integer or floating point type.
+ *
+ * @return the rank if this is an integer or floating point type
+ */
+ public int get_rank () {
+ return rank;
+ }
+
+ /**
* Sets whether this data type has value or reference type semantics.
*
* @param ref_type true if this data type has reference type semantics
}
}
+ private void process_integer_type_attribute (Attribute! a) {
+ integer_type = true;
+ foreach (NamedArgument arg in a.args) {
+ if (arg.name == "rank") {
+ /* this will already be checked during semantic analysis */
+ if (arg.argument is LiteralExpression) {
+ var lit = ((LiteralExpression) arg.argument).literal;
+ if (lit is IntegerLiteral) {
+ rank = ((IntegerLiteral) lit).value.to_int ();
+ }
+ }
+ }
+ }
+ }
+
+ private void process_floating_type_attribute (Attribute! a) {
+ floating_type = true;
+ foreach (NamedArgument arg in a.args) {
+ if (arg.name == "rank") {
+ /* this will already be checked during semantic analysis */
+ if (arg.argument is LiteralExpression) {
+ var lit = ((LiteralExpression) arg.argument).literal;
+ if (lit is IntegerLiteral) {
+ rank = ((IntegerLiteral) lit).value.to_int ();
+ }
+ }
+ }
+ }
+ }
+
/**
* Process all associated attributes.
*/
process_ccode_attribute (a);
} else if (a.name == "ReferenceType") {
process_ref_type_attribute (a);
+ } else if (a.name == "IntegerType") {
+ process_integer_type_attribute (a);
+ } else if (a.name == "FloatingType") {
+ process_floating_type_attribute (a);
}
}
}
}
[CCode (cheader_filename = "glib.h", type_id = "G_TYPE_CHAR", marshaller_type_name = "CHAR")]
+[IntegerType (rank = 1)]
public struct char {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cname = "unsigned char", cheader_filename = "glib.h", type_id = "G_TYPE_UCHAR", marshaller_type_name = "UCHAR")]
+[IntegerType (rank = 2)]
public struct uchar {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cheader_filename = "glib.h", type_id = "G_TYPE_INT", marshaller_type_name = "INT")]
+[IntegerType (rank = 7)]
public struct int {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cname = "unsigned int", cheader_filename = "glib.h", type_id = "G_TYPE_UINT", marshaller_type_name = "UINT")]
+[IntegerType (rank = 8)]
public struct uint {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cheader_filename = "glib.h")]
+[IntegerType (rank = 3)]
public struct short {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cname = "unsigned short", cheader_filename = "glib.h")]
+[IntegerType (rank = 4)]
public struct ushort {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cheader_filename = "glib.h", type_id = "G_TYPE_LONG", marshaller_type_name = "LONG")]
+[IntegerType (rank = 12)]
public struct long {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
}
[CCode (cname = "unsigned long", cheader_filename = "glib.h", type_id = "G_TYPE_ULONG", marshaller_type_name = "ULONG")]
+[IntegerType (rank = 13)]
public struct ulong {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
public ref string! to_string (string! format = "%lu");
}
+[CCode (cname = "gint16", cheader_filename = "glib.h")]
+[IntegerType (rank = 5)]
+public struct int16 {
+}
+
+[CCode (cname = "guint16", cheader_filename = "glib.h")]
+[IntegerType (rank = 6)]
+public struct uint16 {
+}
+
+[CCode (cname = "gint32", cheader_filename = "glib.h")]
+[IntegerType (rank = 9)]
+public struct int32 {
+}
+
+[CCode (cname = "guint32", cheader_filename = "glib.h")]
+[IntegerType (rank = 10)]
+public struct uint32 {
+}
+
[CCode (cname = "gint64", cheader_filename = "glib.h", type_id = "G_TYPE_INT64", marshaller_type_name = "INT64")]
+[IntegerType (rank = 14)]
public struct int64 {
}
[CCode (cname = "guint64", cheader_filename = "glib.h", type_id = "G_TYPE_UINT64", marshaller_type_name = "UINT64")]
+[IntegerType (rank = 15)]
public struct uint64 {
}
[CCode (cname = "float", cheader_filename = "glib.h", type_id = "G_TYPE_FLOAT", marshaller_type_name = "FLOAT")]
+[FloatingType (rank = 1)]
public struct float {
}
[CCode (cname = "double", cheader_filename = "glib.h", type_id = "G_TYPE_DOUBLE", marshaller_type_name = "DOUBLE")]
+[FloatingType (rank = 2)]
public struct double {
}
[CCode (cname = "gunichar", cheader_filename = "glib.h")]
+[IntegerType (rank = 11)]
public struct unichar {
[CCode (cname = "g_unichar_isalnum")]
public bool isalnum ();