Commit 5882cb3d authored by Raffaele Sandrini's avatar Raffaele Sandrini Committed by Raffaele Sandrini

add CreationMethod type; restrict creation methods bodys to contain only

2007-03-03  Raffaele Sandrini  <rasa@gmx.ch>

	* vala/valaattributeprocessor.vala, vala/valamethod.vala,
	  vala/valacodegenerator.vala, vala/valacreationmethod.vala,
	  vala/valasymbolbuilder.vala, vala/valasemanticanalyzer.vala,
	  vala/parser.y, vala/valacodevisitor.vala,
	  vala/valainterfacewriter.vala, vala/valamemorymanager.vala:
	  add CreationMethod type; restrict creation methods bodys to contain
	  only property assignment statements
	* vala/valacharacterliteral.vala, vala/valacodegenerator.vala,
	  vala/valaarray.vala: fix the compiler to obey the new creation
	  method rules
	* vala/Makefile.am: update

svn path=/trunk/; revision=214
parent d2d8fe52
2007-03-03 Raffaele Sandrini <rasa@gmx.ch>
* vala/valaattributeprocessor.vala, vala/valamethod.vala,
vala/valacodegenerator.vala, vala/valacreationmethod.vala,
vala/valasymbolbuilder.vala, vala/valasemanticanalyzer.vala,
vala/parser.y, vala/valacodevisitor.vala,
vala/valainterfacewriter.vala, vala/valamemorymanager.vala:
add CreationMethod type; restrict creation methods bodys to contain
only property assignment statements
* vala/valacharacterliteral.vala, vala/valacodegenerator.vala,
vala/valaarray.vala: fix the compiler to obey the new creation
method rules
* vala/Makefile.am: update
2007-03-03 Jürg Billeter <j@bitron.ch>
* vapi/atk.vala, vapi/cairo.vala, vapi/gdk-2.0.vala, vapi/gtk+-2.0.vala,
......
......@@ -91,6 +91,9 @@ libvala_la_SOURCES = \
valacontinuestatement.c \
valacontinuestatement.h \
valacontinuestatement.vala \
valacreationmethod.c \
valacreationmethod.h \
valacreationmethod.vala \
valadatatype.c \
valadatatype.h \
valadatatype.vala \
......@@ -333,6 +336,7 @@ valainclude_HEADERS = \
valaconstant.h \
valaconstructor.h \
valacontinuestatement.h \
valacreationmethod.h \
valadatatype.h \
valadeclarationstatement.h \
valadestructor.h \
......
......@@ -2302,11 +2302,10 @@ method_header
GList *l;
ValaSourceReference *src = src_com(@5, $1);
$$ = vala_method_new ($6, NULL, src);
$$ = VALA_METHOD (vala_creation_method_new ($6, src));
g_free ($5);
g_free ($6);
g_object_unref (src);
vala_method_set_construction ($$, TRUE);
vala_method_set_instance ($$, FALSE);
if ($3 != 0) {
$$->access = $3;
......
......@@ -53,20 +53,12 @@ public class Vala.Array : DataType {
rank = _rank;
element_type = _element_type;
source_reference = _source_reference;
if (_rank < 1) {
Report.error (null, "internal: attempt to create an array with rank smaller than 1");
}
}
public Array.with_type_parameter (TypeParameter! _element_type_parameter, int _rank, SourceReference! _source_reference) {
rank = _rank;
element_type_parameter = _element_type_parameter;
source_reference = _source_reference;
if (_rank < 1) {
Report.error (null, "internal: attempt to create an array with rank smaller than 1");
}
}
construct {
......@@ -81,6 +73,10 @@ public class Vala.Array : DataType {
name = "%s[%s]".printf (element_type.name, commas); */
if (rank < 1) {
Report.error (null, "internal: attempt to create an array with rank smaller than 1");
}
int i = rank - 1;
if (element_type != null) {
name = "%s[".printf (element_type.name);
......
......@@ -58,6 +58,10 @@ public class Vala.AttributeProcessor : CodeVisitor {
public override void visit_begin_method (Method! m) {
m.process_attributes ();
}
public override void visit_begin_creation_method (CreationMethod! m) {
m.process_attributes ();
}
public override void visit_begin_property (Property! prop) {
prop.process_attributes ();
......
......@@ -55,6 +55,9 @@ public class Vala.CharacterLiteral : Literal {
value = c;
source_reference = source;
}
construct {
if (error) {
Report.error (source_reference, "invalid character literal");
}
......
......@@ -92,7 +92,9 @@ public class Vala.CodeGenerator : CodeVisitor {
public CodeGenerator (bool manage_memory = true) {
memory_management = manage_memory;
}
construct {
predefined_marshal_list = new HashTable (str_hash, str_equal);
predefined_marshal_list.insert ("VOID:VOID", true);
predefined_marshal_list.insert ("VOID:BOOLEAN", true);
......@@ -1253,11 +1255,11 @@ public class Vala.CodeGenerator : CodeVisitor {
}
source_type_member_definition.append (function);
if (m.construction && current_class != null) {
if (m is CreationMethod && current_class != null) {
// declare construction parameter array
var cparamsinit = new CCodeFunctionCall (new CCodeIdentifier ("g_new0"));
cparamsinit.add_argument (new CCodeIdentifier ("GParameter"));
cparamsinit.add_argument (new CCodeConstant (m.n_construction_params.to_string ()));
cparamsinit.add_argument (new CCodeConstant (((CreationMethod)m).n_construction_params.to_string ()));
var cdecl = new CCodeDeclaration ("GParameter *");
cdecl.add_declarator (new CCodeVariableDeclarator.with_initializer ("__params", cparamsinit));
......@@ -1316,7 +1318,7 @@ public class Vala.CodeGenerator : CodeVisitor {
source_type_member_definition.append (vfunc);
}
if (m.construction) {
if (m is CreationMethod) {
var creturn = new CCodeReturnStatement ();
creturn.return_expression = new CCodeIdentifier ("self");
function.block.add_statement (creturn);
......@@ -1348,6 +1350,15 @@ public class Vala.CodeGenerator : CodeVisitor {
}
}
public override void visit_begin_creation_method (CreationMethod! m) {
current_symbol = m.symbol;
current_return_type = m.return_type;
}
public override void visit_end_creation_method (CreationMethod! m) {
visit_end_method (m);
}
private bool is_possible_entry_point (Method! m, ref bool return_value, ref bool args_parameter) {
if (m.name == null || m.name != "main") {
// method must be called "main"
......
......@@ -210,6 +210,22 @@ public abstract class Vala.CodeVisitor {
*/
public virtual void visit_end_method (Method! m) {
}
/**
* Visit operation called at beginning of creation methods.
*
* @param m a method
*/
public virtual void visit_begin_creation_method (CreationMethod! m) {
}
/**
* Visit operation called at end of creation methods.
*
* @param m a method
*/
public virtual void visit_end_creation_method (CreationMethod! m) {
}
/**
* Visit operation called for formal parameters.
......
/* valacreationmethod.vala
*
* Copyright (C) 2007 Raffaele Sandrini
*
* 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:
* Raffaele Sandrini <j@bitron.ch>
*/
using GLib;
/**
* Represents a type creation method.
*/
public class Vala.CreationMethod : Method {
/**
* Specifies the number of parameters this creation method sets.
*/
public int n_construction_params { get; set; }
private string cname;
/**
* Creates a new method.
*
* @param name method name
* @param source reference to source code
* @return newly created method
*/
public CreationMethod (string _name, SourceReference source = null) {
name = _name;
source_reference = source;
}
public override void accept (CodeVisitor! visitor) {
visitor.visit_begin_creation_method (this);
foreach (FormalParameter param in get_parameters()) {
param.accept (visitor);
}
if (body != null) {
body.accept (visitor);
}
visitor.visit_end_creation_method (this);
}
/**
* Returns the interface name of this method as it is used in C code.
*
* @return the name to be used in C code
*/
public override string! get_cname () {
if (cname == null) {
var parent = symbol.parent_symbol.node;
if (parent is DataType) {
if (name == null) {
cname = "%snew".printf (((DataType) parent).get_lower_case_cprefix ());
} else {
cname = "%snew_%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
}
}
}
return cname;
}
}
......@@ -390,7 +390,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
write_indent ();
write_string ("public");
if (m.construction) {
if (m is CreationMethod) {
write_string (" ");
var datatype = (DataType) m.symbol.parent_symbol.node;
write_identifier (datatype.name);
......@@ -407,7 +407,7 @@ public class Vala.InterfaceWriter : CodeVisitor {
write_string (" virtual");
}
if (!m.construction) {
if (!(m is CreationMethod)) {
write_string (" ");
var type = m.return_type.data_type;
......@@ -441,6 +441,10 @@ public class Vala.InterfaceWriter : CodeVisitor {
write_newline ();
}
public override void visit_begin_creation_method (CreationMethod! m) {
visit_begin_method (m);
}
public override void visit_begin_property (Property! prop) {
if (internal_scope) {
......
......@@ -74,6 +74,10 @@ public class Vala.MemoryManager : CodeVisitor {
current_symbol = m.symbol;
}
public override void visit_begin_creation_method (CreationMethod! m) {
current_symbol = m.symbol;
}
public override void visit_begin_property (Property! prop) {
current_symbol = prop.symbol;
}
......
......@@ -77,16 +77,6 @@ public class Vala.Method : Member, Invokable {
* of a base type.
*/
public bool overrides { get; set; }
/**
* Specifies whether this is a construction method.
*/
public bool construction { get; set; }
/**
* Specifies the number of parameters this construction method sets.
*/
public int n_construction_params { get; set; }
/**
* Specifies whether the C method returns a new instance pointer which
......@@ -207,19 +197,11 @@ public class Vala.Method : Member, Invokable {
*
* @return the name to be used in C code
*/
public string! get_cname () {
public virtual string! get_cname () {
if (cname == null) {
var parent = symbol.parent_symbol.node;
if (parent is DataType) {
if (construction) {
if (name == null) {
cname = "%snew".printf (((DataType) parent).get_lower_case_cprefix ());
} else {
cname = "%snew_%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
}
} else {
cname = "%s%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
}
cname = "%s%s".printf (((DataType) parent).get_lower_case_cprefix (), name);
} else if (parent is Namespace) {
cname = "%s%s".printf (((Namespace) parent).get_lower_case_cprefix (), name);
} else {
......
......@@ -168,30 +168,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
}
}
public override void visit_begin_method (Method! m) {
if (m.construction) {
m.return_type = new TypeReference ();
m.return_type.data_type = (DataType) current_symbol.node;
m.return_type.transfers_ownership = true;
if (current_symbol.node is Class) {
// check for floating reference
var cl = (Class) current_symbol.node;
while (cl != null) {
if (cl == initially_unowned_type) {
m.return_type.floating_reference = true;
break;
}
cl = cl.base_class;
}
}
if (m.body != null) {
m.body.construction = true;
}
}
public override void visit_begin_method (Method! m) {
current_symbol = m.symbol;
current_return_type = m.return_type;
......@@ -259,13 +236,45 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
return;
}
}
}
public override void visit_begin_creation_method (CreationMethod! m) {
m.return_type = new TypeReference ();
m.return_type.data_type = (DataType) current_symbol.node;
m.return_type.transfers_ownership = true;
if (current_symbol.node is Class) {
// check for floating reference
var cl = (Class) current_symbol.node;
while (cl != null) {
if (cl == initially_unowned_type) {
m.return_type.floating_reference = true;
break;
}
cl = cl.base_class;
}
}
if (m.body != null) {
m.body.construction = true;
}
if (m.construction && m.body != null) {
current_symbol = m.symbol;
current_return_type = m.return_type;
}
public override void visit_end_creation_method (CreationMethod! m) {
visit_end_method (m);
if (m.body != null) {
int n_params = 0;
foreach (Statement stmt in m.body.get_statements ()) {
int params = stmt.get_number_of_set_construction_parameters ();
if (params == -1) {
break;
m.error = true;
Report.error (stmt.source_reference, "type creation methods only allow property assignment statements");
return;
}
n_params += params;
stmt.construction = true;
......@@ -1125,7 +1134,7 @@ public class Vala.SemanticAnalyzer : CodeVisitor {
type_node = constructor_node.symbol.parent_symbol.node;
var constructor = (Method) constructor_node;
if (!constructor.construction) {
if (!(constructor_node is CreationMethod)) {
expr.error = true;
Report.error (expr.source_reference, "`%s' is not a construction method".printf (constructor.symbol.get_full_name ()));
return;
......
......@@ -186,23 +186,7 @@ public class Vala.SymbolBuilder : CodeVisitor {
return;
}
if (m.construction) {
var type_node = m.symbol.parent_symbol.node;
if (!(type_node is Class || type_node is Struct)) {
Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
m.error = true;
return;
}
if (m.name == null) {
if (type_node is Class) {
((Class) type_node).default_construction_method = m;
} else if (type_node is Struct) {
((Struct) type_node).default_construction_method = m;
}
}
} else if (m.instance) {
if (m.instance) {
if (!(m.symbol.parent_symbol.node is DataType)) {
Report.error (m.source_reference, "instance methods not allowed outside of data types");
......@@ -227,6 +211,39 @@ public class Vala.SymbolBuilder : CodeVisitor {
current_symbol = current_symbol.parent_symbol;
}
public override void visit_begin_creation_method (CreationMethod! m) {
if (add_symbol (m.name, m) == null) {
return;
}
var type_node = m.symbol.parent_symbol.node;
if (!(type_node is Class || type_node is Struct)) {
Report.error (m.source_reference, "construction methods may only be declared within classes and structs");
m.error = true;
return;
}
if (m.name == null) {
if (type_node is Class) {
((Class) type_node).default_construction_method = m;
} else if (type_node is Struct) {
((Struct) type_node).default_construction_method = m;
}
}
current_symbol = m.symbol;
}
public override void visit_end_creation_method (CreationMethod! m) {
if (m.error) {
/* skip methods with errors */
return;
}
current_symbol = current_symbol.parent_symbol;
}
public override void visit_formal_parameter (FormalParameter! p) {
if (!p.ellipsis) {
......
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