[prettyprint] r586 committed - Split Definition from DefinitionStatement. This leaves type_test (and...

0 views
Skip to first unread message

prett...@googlecode.com

unread,
Jul 7, 2010, 12:02:00 AM7/7/10
to pp-d...@googlegroups.com
Revision: 586
Author: thockin
Date: Tue Jul 6 21:00:55 2010
Log: Split Definition from DefinitionStatement. This leaves type_test (and
indeed Type) broken. Must fix ASAP.


http://code.google.com/p/prettyprint/source/detail?r=586

Modified:
/trunk/language/TODO.language
/trunk/language/environment.cpp
/trunk/language/environment.h
/trunk/language/grammar.y
/trunk/language/parsed_file.h
/trunk/language/syntax_tree.cpp
/trunk/language/syntax_tree.h
/trunk/language/type.cpp
/trunk/language/type.h

=======================================
--- /trunk/language/TODO.language Fri Jul 2 17:29:57 2010
+++ /trunk/language/TODO.language Tue Jul 6 21:00:55 2010
@@ -24,3 +24,5 @@
allow 'list<>' === 'list', but not 'int<>'

better syntax errors when yacc blows up
+
+map<k, v>
=======================================
--- /trunk/language/environment.cpp Thu Jun 24 17:50:36 2010
+++ /trunk/language/environment.cpp Tue Jul 6 21:00:55 2010
@@ -58,10 +58,10 @@
return warns;
}

-syntax::DefinitionStatement *
+syntax::Definition *
Environment::lookup_symbol(const string &name)
{
- syntax::DefinitionStatement * const *p = m_symtab.lookup(name);
+ syntax::Definition * const *p = m_symtab.lookup(name);
if (p == NULL) {
return NULL;
}
=======================================
--- /trunk/language/environment.h Sun Jul 4 10:58:50 2010
+++ /trunk/language/environment.h Tue Jul 6 21:00:55 2010
@@ -16,7 +16,7 @@
// Forward declarations.
class ParsedFile;
namespace syntax {
- class DefinitionStatement;
+ class Definition;
class Identifier;
}

@@ -112,7 +112,7 @@
// Add a symbol to the current nested scope. This is used while
// validating parsed files to do symbol resolution.
bool
- add_symbol(const string &name, syntax::DefinitionStatement *definition)
+ add_symbol(const string &name, syntax::Definition *definition)
{
return m_symtab.add_unique(name,definition);
}
@@ -127,7 +127,7 @@

// Look up a symbol by name in the current nested scope hierarchy.
// This is used while validating parsed files to do symbol resolution.
- syntax::DefinitionStatement *
+ syntax::Definition *
lookup_symbol(const string &name);

const ParsedFile *
@@ -135,7 +135,7 @@

private:
Parser m_parser;
- util::SymbolTable<string, syntax::DefinitionStatement*> m_symtab;
+ util::SymbolTable<string, syntax::Definition*> m_symtab;
ParsedFileMap m_parsed_files; // Owns the ParsedFile pointers.
ModuleMap m_modules;
};
=======================================
--- /trunk/language/grammar.y Wed Jun 30 17:49:16 2010
+++ /trunk/language/grammar.y Tue Jul 6 21:00:55 2010
@@ -1029,10 +1029,10 @@
: definition_statement {
SYNTRACE("file_scope_item", "definition_statement");
// Save all the top-level symbols.
- const InitializedIdentifierList *init_ident_list = $1->vars();
- for (size_t i = 0; i < init_ident_list->size(); i++) {
- string symbol = init_ident_list->at(i)->identifier()->symbol();
- if (out_parsed_file->add_private_symbol(symbol, $1)) {
+ const DefinitionList &defn_list = $1->vars();
+ for (size_t i = 0; i < defn_list.size(); i++) {
+ string symbol = defn_list[i]->identifier()->symbol();
+ if (out_parsed_file->add_private_symbol(symbol, defn_list[i])) {
throw SyntaxError(curpos(),
sprintfxx("symbol '%s' redefined", symbol));
}
@@ -1042,15 +1042,14 @@
| TOK_PUBLIC definition_statement {
SYNTRACE("file_scope_item", "PUBLIC definition_statement");
// Save all the top-level symbols.
- const InitializedIdentifierList *init_ident_list = $2->vars();
- for (size_t i = 0; i < init_ident_list->size(); i++) {
- string symbol = init_ident_list->at(i)->identifier()->symbol();
- if (out_parsed_file->add_public_symbol(symbol, $2)) {
+ const DefinitionList &defn_list = $2->vars();
+ for (size_t i = 0; i < defn_list.size(); i++) {
+ string symbol = defn_list[i]->identifier()->symbol();
+ if (out_parsed_file->add_public_symbol(symbol, defn_list[i])) {
throw SyntaxError(curpos(),
sprintfxx("symbol '%s' redefined", symbol));
}
}
- $2->set_public();
$$ = $2;
}
| discover_statement {
=======================================
--- /trunk/language/parsed_file.h Thu Jun 24 07:46:16 2010
+++ /trunk/language/parsed_file.h Tue Jul 6 21:00:55 2010
@@ -38,7 +38,7 @@
string module;
string symbol;
};
- typedef std::map<Symbol, syntax::DefinitionStatement*> SymbolMap;
+ typedef std::map<Symbol, syntax::Definition*> SymbolMap;
typedef SymbolMap::const_iterator SymbolIterator;

ParsedFile()
@@ -114,7 +114,7 @@
return m_private_symbols.end();
}
#if 0 // FIXME: handle symbols, handle "same as mine" module semantic
- syntax::DefinitionStatement *
+ syntax::Definition *
public_symbol(const string &name) const
{
SymbolIterator it = m_public_symbols.find(name);
@@ -123,7 +123,7 @@
}
return it->second;
}
- syntax::DefinitionStatement *
+ syntax::Definition *
private_symbol(const string &name) const
{
SymbolIterator it = m_private_symbols.find(name);
@@ -135,23 +135,21 @@
#endif
// Returns true if the symbol already existed.
bool
- add_public_symbol(const string &name,
- syntax::DefinitionStatement *definition)
+ add_public_symbol(const string &name, syntax::Definition *definition)
{
Symbol sym(m_module, name);
- const syntax::DefinitionStatement *p = m_public_symbols[sym];
+ const syntax::Definition *def = m_public_symbols[sym];
m_public_symbols[sym] = definition;
- return p;
+ return def;
}
// Returns true if the symbol already existed.
bool
- add_private_symbol(const string &name,
- syntax::DefinitionStatement *definition)
+ add_private_symbol(const string &name, syntax::Definition *definition)
{
Symbol sym(m_module, name);
- const syntax::DefinitionStatement *p = m_private_symbols[sym];
+ const syntax::Definition *def = m_private_symbols[sym];
m_private_symbols[sym] = definition;
- return p;
+ return def;
}

private:
=======================================
--- /trunk/language/syntax_tree.cpp Sun Jul 4 10:58:50 2010
+++ /trunk/language/syntax_tree.cpp Tue Jul 6 21:00:55 2010
@@ -22,7 +22,7 @@
{
string ret = m_ident->to_string();
if (m_init) {
- ret += " = " + m_init->to_string() + "\n";
+ ret += " = " + m_init->to_string();
}
return ret;
}
@@ -204,14 +204,10 @@
DefinitionStatement::to_string() const
{
string ret = Statement::to_string();
- ret += m_type->to_string() + " ";
- for (size_t i = 0; i < m_vars->size(); i++) {
- if (i > 0) {
- ret += ", ";
- }
- ret += m_vars->at(i)->to_string();
- }
- ret += "\n";
+ for (size_t i = 0; i < m_vars.size(); i++) {
+ ret += m_vars[i]->to_string();
+ ret += ";\n";
+ }
return ret;
}

=======================================
--- /trunk/language/syntax_tree.h Sun Jul 4 14:17:32 2010
+++ /trunk/language/syntax_tree.h Tue Jul 6 21:00:55 2010
@@ -25,11 +25,12 @@
class SyntaxNode {
public:
enum NodeType {
- TYPE_IDENTIFIER, // a symbol name
- TYPE_EXPRESSION, // an expression produces a value
- TYPE_STATEMENT, // a statement executes
- TYPE_ARGUMENT, // a named argument (e.g. function call)
- TYPE_PARAMETER, // a parameter declaration
+ NODE_TYPE_IDENTIFIER, // a symbol name
+ NODE_TYPE_DEFINITION, // an object definition
+ NODE_TYPE_EXPRESSION, // an expression produces a value
+ NODE_TYPE_STATEMENT, // a statement executes
+ NODE_TYPE_ARGUMENT, // a named argument (e.g. function call)
+ NODE_TYPE_PARAMETER, // a parameter declaration
};

NodeType
@@ -91,7 +92,7 @@
public:
explicit
Expression(const Parser::Position &pos)
- : SyntaxNode(pos, TYPE_EXPRESSION), m_result_type(Type::VAR)
+ : SyntaxNode(pos, NODE_TYPE_EXPRESSION), m_result_type(Type::VAR)
{
}

@@ -134,13 +135,13 @@
class Identifier : public SyntaxNode {
public:
Identifier(const Parser::Position &pos, const string &symbol)
- : SyntaxNode(pos, TYPE_IDENTIFIER),
+ : SyntaxNode(pos, NODE_TYPE_IDENTIFIER),
m_module(""), m_symbol(symbol)
{
}
Identifier(const Parser::Position &pos,
const string &module, const string &symbol)
- : SyntaxNode(pos, TYPE_IDENTIFIER),
+ : SyntaxNode(pos, NODE_TYPE_IDENTIFIER),
m_module(module), m_symbol(symbol)
{
}
@@ -155,7 +156,7 @@
return m_symbol;
}

- const DefinitionStatement *
+ const Definition *
definition() const
{
return m_definition;
@@ -173,19 +174,19 @@
private:
string m_module;
string m_symbol;
- DefinitionStatement *m_definition;
+ Definition *m_definition;
};

class InitializedIdentifier : public SyntaxNode {
public:
InitializedIdentifier(const Parser::Position &pos, Identifier *ident)
- : SyntaxNode(pos, TYPE_IDENTIFIER),
+ : SyntaxNode(pos, NODE_TYPE_IDENTIFIER),
m_ident(ident), m_init(NULL)
{
}
InitializedIdentifier(const Parser::Position &pos,
Identifier *ident, Expression *init)
- : SyntaxNode(pos, TYPE_IDENTIFIER),
+ : SyntaxNode(pos, NODE_TYPE_IDENTIFIER),
m_ident(ident), m_init(init)
{
}
@@ -222,7 +223,7 @@
public:
explicit
Statement(const Parser::Position &pos)
- : SyntaxNode(pos, TYPE_STATEMENT), m_labels(NULL)
+ : SyntaxNode(pos, NODE_TYPE_STATEMENT), m_labels(NULL)
{
}
virtual
@@ -265,15 +266,138 @@
};
typedef std::vector<Statement*> StatementList;

+class Definition : public SyntaxNode {
+ public:
+ Definition(const Parser::Position &pos,
+ const Type &type, InitializedIdentifier *init_ident)
+ : SyntaxNode(pos, NODE_TYPE_DEFINITION),
+ m_type(type), m_init_ident(init_ident)
+ {
+ }
+
+ const Type &
+ type()
+ {
+ return m_type;
+ }
+
+ InitializedIdentifier *
+ init_ident()
+ {
+ return m_init_ident.get();
+ }
+
+ Identifier *
+ identifier() const
+ {
+ return m_init_ident->identifier();
+ }
+
+ Expression *
+ initializer() const
+ {
+ return m_init_ident->initializer();
+ }
+
+ // FIXME: move to .cpp file
+ virtual string
+ to_string() const
+ {
+ return m_type.to_string() + " " + m_init_ident->to_string();
+ }
+
+ virtual int
+ validate(const ValidateOptions &flags, Environment *env)
+ {
+ int warnings = m_init_ident->validate_once(flags, env);
+
+ Expression *init_expr = m_init_ident->initializer();
+
+ // Some types are not completely defined until init time.
+ detect_final_type_from_init(&m_type, init_expr);
+
+ //FIXME: undo flexibility inside Type, call sanity_check()
+ // Make sure the type can be initialized correctly.
+ if (init_expr != NULL
+ && !m_type.is_initializable_from(init_expr->result_type())) {
+ throw SyntaxError(parse_position(),
+ sprintfxx("can't init type '%s' from '%s'",
+ m_type.to_string(),
+ init_expr->result_type().to_string()));
+ }
+
+ // Keep track of the symbol, making sure it does not already exist.
+ string symbol = m_init_ident->identifier()->symbol();
+ if (env->add_symbol(symbol, this) == false) {
+ throw SyntaxError(parse_position(),
+ sprintfxx("symbol '%s' redefined", symbol));
+ }
+ return warnings;
+ }
+
+ private:
+ Type m_type;
+ util::NeverNullScopedPtr<InitializedIdentifier> m_init_ident;
+
+ //FIXME: move to .cpp, make file static
+ void
+ detect_final_type_from_init(Type *type, Expression *init_expr)
+ //FIXME: handle list<list>
+ //FIXME: list x = [0]; => list<int-literal>. Const is bad.
+ {
+ // Handle "list x;" style definitions. If there is no initializer,
+ // it is equivalent to "list<var> x;". Otherwise we'll try to
+ // detect the best type-arg.
+ if (type->primitive() == Type::LIST && type->n_arguments() == 0) {
+ if (init_expr == NULL) {
+ type->add_argument(Type::VAR);
+ return;
+ }
+
+ const Type &init_type = init_expr->result_type();
+ if (init_type.primitive() == Type::LIST) {
+ type->add_argument(init_type.argument(0));
+ } else if (init_type.primitive() == Type::TUPLE) {
+ Type arg_type = init_type.argument(0);
+ for (size_t i = 1; i < init_type.n_arguments(); i++) {
+ if (init_type.argument(i) != arg_type) {
+ arg_type.reinit(Type::VAR);
+ break;
+ }
+ }
+ type->add_argument(arg_type);
+ }
+ return;
+ }
+
+ // Handle "tuple t;" style definitions. If there is no initializer,
+ // it is an error. Otherwise we'll try to detect the type-args.
+ if (type->primitive() == Type::TUPLE && type->n_arguments() == 0) {
+ if (init_expr == NULL) {
+ throw SyntaxError(parse_position(),
+ "zero-argument tuple definitions must be initialized");
+ }
+
+ const Type &init_type = init_expr->result_type();
+ if (init_type.primitive() == Type::TUPLE) {
+ for (size_t i = 0; i < init_type.n_arguments(); i++) {
+ type->add_argument(init_type.argument(i));
+ }
+ }
+ }
+ }
+};
+typedef std::vector<Definition*> DefinitionList;
+
class Argument : public SyntaxNode {
public:
Argument(const Parser::Position &pos, Expression *expr)
- : SyntaxNode(pos, TYPE_ARGUMENT), m_name(NULL), m_expr(expr)
+ : SyntaxNode(pos, NODE_TYPE_ARGUMENT), m_name(NULL), m_expr(expr)
{
}
Argument(const Parser::Position &pos,
Identifier *name, Expression *expr)
- : SyntaxNode(pos, TYPE_ARGUMENT), m_name(name), m_expr(expr)
+ : SyntaxNode(pos, NODE_TYPE_ARGUMENT), m_name(name), m_expr(expr)
{
}

@@ -638,63 +762,44 @@
class DefinitionStatement : public Statement {
public:
DefinitionStatement(const Parser::Position &pos,
- Type *type, InitializedIdentifierList *vars)
- : Statement(pos), m_public(false), m_type(type), m_vars(vars)
- {
- }
-
- Type *type() const
- {
- return m_type.get();
+ Type *def_type, InitializedIdentifierList *def_vars)
+ : Statement(pos)
+ {
+ // Just for RAII.
+ util::NeverNullScopedPtr<Type> type_ptr(def_type);
+ util::NeverNullScopedPtr<InitializedIdentifierList> vars_ptr(def_vars);
+
+ // Expand "int x=0, y, z=1;" into "int x=0; int y; int z=1;" for
+ // easier use later.
+ for (size_t i = 0; i < def_vars->size(); i++) {
+ m_vars.push_back(new Definition(pos, *def_type, def_vars->at(i)));
+ }
}

- InitializedIdentifierList *vars() const
- {
- return m_vars.get();
+ const DefinitionList &
+ vars() const
+ {
+ return m_vars;
}

- void set_public()
- {
- m_public = true;
- }
-
- virtual bool execute();
-
- virtual string to_string() const;
-
- virtual int validate(const ValidateOptions &flags, Environment *env)
+ virtual bool
+ execute();
+
+ virtual string
+ to_string() const;
+
+ virtual int
+ validate(const ValidateOptions &flags, Environment *env)
{
int warnings = Statement::validate(flags, env);
-
- // For each defined variable...
- for (size_t i = 0; i < m_vars->size(); i++) {
- InitializedIdentifier *init_ident = m_vars->at(i);
- warnings += init_ident->validate_once(flags, env);
-
- //FIXME: make list and tuple initializaeble without args
- // Make sure the type can be initialized correctly.
- Expression *expr = init_ident->initializer();
- if (expr && !m_type->is_initializable_from(expr->result_type())) {
- throw SyntaxError(parse_position(),
- sprintfxx("can't init type '%s' from '%s'",
- m_type->to_string(),
- expr->result_type().to_string()));
- }
-
- // Keep track of the symbol, making sure it does not already exist.
- string symbol = init_ident->identifier()->symbol();
- if (env->add_symbol(symbol, this) == false) {
- throw SyntaxError(parse_position(),
- sprintfxx("symbol '%s' redefined", symbol));
- }
+ for (size_t i = 0; i < m_vars.size(); i++) {
+ warnings += m_vars[i]->validate_once(flags, env);
}
return warnings;
}

private:
- bool m_public;
- util::NeverNullScopedPtr<Type> m_type;
- util::NeverNullScopedPtr<InitializedIdentifierList> m_vars;
+ DefinitionList m_vars;
};

class ImportStatement : public Statement {
@@ -801,7 +906,7 @@
virtual int
validate(const ValidateOptions &flags, Environment *env)
{
- DefinitionStatement *def = env->lookup_symbol(m_ident->symbol());
+ Definition *def = env->lookup_symbol(m_ident->symbol());
if (!def) {
string why = "symbol '" + to_string() + "' can't be resolved";
if (flags.error_on_unresolved_symbols()) {
@@ -812,7 +917,7 @@
return 1;
}
int warnings = def->validate_once(flags, env);
- set_result_type(*(def->type()));
+ set_result_type(def->type());
m_definition = def;
return warnings;
}
@@ -830,7 +935,7 @@

private:
util::NeverNullScopedPtr<Identifier> m_ident;
- DefinitionStatement *m_definition; // cached for easy access
+ Definition *m_definition; // cached for easy access
};

class SubscriptExpression : public Expression {
@@ -894,28 +999,31 @@
// Tuples have zero or more type-args. If the index is a constexpr,
// we know the type. If it is not, this expression must be runtime
// evaluated.
- if (expr_prim == Type::TUPLE && m_index->is_constexpr()) {
- //FIXME: const tuple t = [ false ]; bool b = t[0]; must succeed.
- //FIXME: const tuple t = [ false ]; int i = t[0]; must fail.
- try {
- Variable v(Type::INT);
- m_index->evaluate(&v);
- size_t index = v.int_value().as_uint();
- if (index >= expr_type.n_arguments()) {
- string why = sprintfxx("type '%s' has no [%d] member",
- expr_type.to_string(),
- index);
+ if (expr_prim == Type::TUPLE) {
+ if (m_index->is_constexpr()) {
+ //FIXME: const tuple t = [ false ]; bool b = t[0]; must succeed.
+ //FIXME: const tuple t = [ false ]; int i = t[0]; must fail.
+ try {
+ Variable v(Type::INT);
+ m_index->evaluate(&v);
+ size_t index = v.int_value().as_uint();
+ if (index >= expr_type.n_arguments()) {
+ string why = sprintfxx(
+ "type '%s' has no [%d] member",
+ expr_type.to_string(), index);
+ throw SyntaxError(parse_position(), why);
+ }
+ set_result_type(expr_type.argument(index));
+ } catch (Variable::TypeError &type_error) {
+ string why = sprintfxx(
+ "subscript index must be type '%s', found type '%s'",
+ Type::primitive_to_string(Type::INT),
+ index_type.to_string());
throw SyntaxError(parse_position(), why);
}
- set_result_type(expr_type.argument(index));
- } catch (Variable::TypeError &type_error) {
- string why = "subscript index must be type '"
- + Type::primitive_to_string(Type::INT)
- + "', found type '" + index_type.to_string() + "'";
- throw SyntaxError(parse_position(), why);
- }
- } else {
- set_result_type(Type::VAR);
+ } else {
+ set_result_type(Type::VAR);
+ }
}
return warnings;
}
@@ -1336,7 +1444,7 @@
public:
ParameterDeclaration(const Parser::Position &pos,
Type *type, Identifier *ident)
- : SyntaxNode(pos, TYPE_PARAMETER), m_type(type), m_ident(ident)
+ : SyntaxNode(pos, NODE_TYPE_PARAMETER), m_type(type), m_ident(ident)
{
}

@@ -1438,7 +1546,7 @@
{
int warnings = 0;
env->new_symbol_scope();
- static DefinitionStatement *args_defn = new_args_definition();
+ static Definition *args_defn = new_args_definition();
env->add_symbol("args", args_defn);
warnings += m_body->validate_once(flags, env);
for (size_t i = 0; i < m_params->size(); i++) {
@@ -1455,17 +1563,16 @@
}

private:
- // Make a new DefinitionStatement that is the built-in function args list.
- DefinitionStatement *
+ // Make a new Definition that is the built-in function args list.
+ Definition *
new_args_definition()
{
const Parser::Position &pos = parse_position();
- Type *args_type = (new Type(Type::LIST))->add_argument(Type::VAR);
- InitializedIdentifierList *ident_list = new InitializedIdentifierList();
- ident_list->push_back(
- new InitializedIdentifier(pos, new Identifier(pos, "args")));
-
- return new DefinitionStatement(pos, args_type, ident_list);
+ Type type(Type::LIST);
+ type.add_argument(Type::VAR);
+ InitializedIdentifier *init_ident
+ = new InitializedIdentifier(pos, new Identifier(pos, "args"));
+ return new Definition(pos, type, init_ident);
}

util::NeverNullScopedPtr<ParameterDeclarationList> m_params;
=======================================
--- /trunk/language/type.cpp Fri Jul 2 17:29:57 2010
+++ /trunk/language/type.cpp Tue Jul 6 21:00:55 2010
@@ -9,7 +9,7 @@
Type::Type(const Type &other)
{
m_primitive = other.m_primitive;
- m_is_const = other.m_is_const;
+ m_constness = other.m_constness;
for (size_t i = 0; i < other.m_arguments.size(); i++) {
m_arguments.push_back(other.m_arguments[i]);
}
@@ -21,7 +21,7 @@
// Clean up arguments.
m_arguments.clear();
m_primitive = prim;
- m_is_const = 0;
+ m_constness = 0;
return this;
}
Type *
@@ -30,7 +30,7 @@
// Clean up arguments.
m_arguments.clear();
m_primitive = prim;
- m_is_const = constness;
+ m_constness = constness;
return this;
}

=======================================
--- /trunk/language/type.h Fri Jul 2 17:29:57 2010
+++ /trunk/language/type.h Tue Jul 6 21:00:55 2010
@@ -59,11 +59,11 @@

// Implicit conversion is OK.
Type(Primitive prim)
- : m_primitive(prim), m_is_const(0), m_arguments()
+ : m_primitive(prim), m_constness(0), m_arguments()
{
}
Type(Primitive prim, Constness constness)
- : m_primitive(prim), m_is_const(constness), m_arguments()
+ : m_primitive(prim), m_constness(constness), m_arguments()
{
}
// Make a deep-copy.
@@ -130,20 +130,20 @@
bool
is_const() const
{
- return m_is_const != 0;
+ return m_constness != 0;
}

Type *
set_const()
{
- m_is_const = CONST;
+ m_constness = CONST;
return this;
}

bool
is_literal() const
{
- return m_is_const == LITERAL;
+ return m_constness == LITERAL;
}

size_t
@@ -173,8 +173,9 @@
// In general, constness applies to a Variable, not a Type. In order
// to make Type arguments and some literal assigments easier, we keep a
// notion of constness here, which we can copy into Variables as they are
- // created.
- int m_is_const;
+ // created. This is 'int' rather than 'Constness' so we can set it
+ // to 0 without exposing a NON_CONST enum value.
+ int m_constness;
std::vector<Type> m_arguments;
};

Reply all
Reply to author
Forward
0 new messages