Commit be3441b3 authored by Jürg Billeter's avatar Jürg Billeter Committed by Jürg Billeter

use IntegerType, FloatingType, and rank attributes to analyze arithmetic

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

svn path=/trunk/; revision=117
parent bcaee210
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
......
......@@ -27,7 +27,7 @@ using GLib;
*/
public class Vala.CCodeCastExpression : CCodeExpression {
/**
* The expression to be casted.
* The expression to be cast.
*/
public CCodeExpression! inner { get; set construct; }
......
......@@ -27,7 +27,7 @@ using GLib;
*/
public class Vala.CastExpression : Expression {
/**
* The expression to be casted.
* The expression to be cast.
*/
public Expression! inner { get; set construct; }
......@@ -39,7 +39,7 @@ public class Vala.CastExpression : Expression {
/**
* 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
*/
......
......@@ -1367,6 +1367,7 @@ public class Vala.CodeGenerator : CodeVisitor {
&& 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 ()) {
......@@ -1899,6 +1900,7 @@ public class Vala.CodeGenerator : CodeVisitor {
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 {
......@@ -1935,6 +1937,7 @@ public class Vala.CodeGenerator : CodeVisitor {
/* 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;
......@@ -1999,6 +2002,7 @@ public class Vala.CodeGenerator : CodeVisitor {
/* 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;
......@@ -2009,6 +2013,7 @@ public class Vala.CodeGenerator : CodeVisitor {
} 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);
......@@ -2129,6 +2134,7 @@ public class Vala.CodeGenerator : CodeVisitor {
}
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;
......@@ -2161,6 +2167,7 @@ public class Vala.CodeGenerator : CodeVisitor {
}
}
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;
......@@ -2360,6 +2367,7 @@ public class Vala.CodeGenerator : CodeVisitor {
&& 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;
......@@ -2438,8 +2446,9 @@ public class Vala.CodeGenerator : CodeVisitor {
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);
}
......
......@@ -32,7 +32,7 @@ public class Vala.InstanceCast : CCodeFunctionCall {
public DataType! type_reference { get; set construct; }
/**
* The expression to be casted.
* The expression to be cast.
*/
public CCodeExpression! inner { get; set construct; }
......
......@@ -783,7 +783,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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 () ||
......@@ -807,54 +807,21 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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);
......@@ -1157,6 +1124,8 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
/* 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);
......@@ -1172,6 +1141,38 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
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 */
......@@ -1192,26 +1193,24 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
|| 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
......
......@@ -26,21 +26,24 @@ using GLib;
* 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.
......@@ -182,6 +185,33 @@ public class Vala.Struct : DataType {
return reference_type;
}
/**
* 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.
*
......@@ -263,6 +293,36 @@ public class Vala.Struct : DataType {
}
}
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.
*/
......@@ -272,6 +332,10 @@ public class Vala.Struct : DataType {
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);
}
}
}
......
......@@ -29,6 +29,7 @@ public struct pointer {
}
[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")]
......@@ -36,6 +37,7 @@ public struct char {
}
[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")]
......@@ -43,6 +45,7 @@ public struct uchar {
}
[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")]
......@@ -50,6 +53,7 @@ public struct int {
}
[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")]
......@@ -57,6 +61,7 @@ public struct uint {
}
[CCode (cheader_filename = "glib.h")]
[IntegerType (rank = 3)]
public struct short {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
......@@ -64,6 +69,7 @@ public struct short {
}
[CCode (cname = "unsigned short", cheader_filename = "glib.h")]
[IntegerType (rank = 4)]
public struct ushort {
[InstanceLast ()]
[CCode (cname = "g_strdup_printf")]
......@@ -71,6 +77,7 @@ public struct ushort {
}
[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")]
......@@ -78,29 +85,55 @@ public struct long {
}
[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 ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment