http://code.google.com/p/prettyprint/source/detail?r=583
Modified:
/trunk/language/TODO.language
/trunk/language/syntax_tree.h
/trunk/language/tests/type_test.cpp
/trunk/language/type.cpp
/trunk/language/type.h
/trunk/language/variable.cpp
=======================================
--- /trunk/language/TODO.language Wed Jun 30 17:50:41 2010
+++ /trunk/language/TODO.language Fri Jul 2 17:29:57 2010
@@ -5,9 +5,6 @@
Define how to convert non-strings to strings, including formatting (hex,
etc)
-list x = [ 1, 2 ]; // detect x as list<int>
-tuple x = [ 1, "2" ]; // detext x as tuple<int, string>
-
make func take type args and check them for type safety
Can I find a way to name tuple members?
@@ -23,3 +20,7 @@
typedef
struct and struct literals
+
+allow 'list<>' === 'list', but not 'int<>'
+
+better syntax errors when yacc blows up
=======================================
--- /trunk/language/syntax_tree.h Fri Jul 2 11:05:20 2010
+++ /trunk/language/syntax_tree.h Fri Jul 2 17:29:57 2010
@@ -655,14 +655,12 @@
{
int warnings = Statement::validate(flags, env);
- // Validate that the type is acceptable, and not ill-formed.
- m_type->sanity_check();
-
// 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())) {
=======================================
--- /trunk/language/tests/type_test.cpp Wed Jun 30 17:44:50 2010
+++ /trunk/language/tests/type_test.cpp Fri Jul 2 17:29:57 2010
@@ -206,6 +206,27 @@
TEST_ASSERT(!t1.is_assignable_from(t2));
TEST_ASSERT(!t2.is_assignable_from(t1));
}
+ // list<> = list<>
+ {
+ Type t1(Type::LIST);
+
+ Type t2(Type::TUPLE);
+
+ TEST_ASSERT(t1.is_equal_to(t2));
+ TEST_ASSERT(t1.is_assignable_from(t2));
+ TEST_ASSERT(t2.is_assignable_from(t1));
+ }
+ // list<> = list<int>
+ {
+ Type t1(Type::LIST);
+
+ Type t2(Type::TUPLE);
+ t2.add_argument(Type::INT);
+
+ TEST_ASSERT(!t1.is_equal_to(t2));
+ TEST_ASSERT(t1.is_assignable_from(t2));
+ TEST_ASSERT(!t2.is_assignable_from(t1));
+ }
// list<list<int>> = list<list<int>>
{
Type t1(Type::LIST);
=======================================
--- /trunk/language/type.cpp Fri Jul 2 11:05:20 2010
+++ /trunk/language/type.cpp Fri Jul 2 17:29:57 2010
@@ -41,7 +41,7 @@
case LIST:
if (m_arguments.size() > 0) {
throw ArgumentError(sprintfxx(
- "type '%s' takes exactly one argument",
+ "type '%s' takes zero or one arguments",
primitive_to_string(m_primitive)));
}
// ...else fall through
@@ -161,16 +161,31 @@
return false;
}
}
- // VAR is assignable from anything. Assignments from var are checked
+ // VAR is assignable from anything. Assignments from VAR are checked
// at runtime.
if (m_primitive == VAR || other.m_primitive == VAR) {
return true;
}
- // Special case: list is assignable from tuple, as long as args match.
- // Otherwise, we apply some other rules.
+ // Special case: LIST with no type args can be assigned from any LIST or
+ // TUPLE.
+ if (m_primitive == LIST && m_arguments.size() == 0) {
+ if (other.m_primitive == LIST || other.m_primitive == TUPLE) {
+ return true;
+ }
+ return false;
+ }
+ // Special case: TUPLE with no type args can be assigned from any TUPLE.
+ if (m_primitive == TUPLE && m_arguments.size() == 0) {
+ if (other.m_primitive == TUPLE) {
+ return true;
+ }
+ return false;
+ }
+ // Special case: LIST is assignable from TUPLE, as long as the type-args
+ // allow it.
if (m_primitive == LIST && other.m_primitive == TUPLE) {
- // We can only assign list = tuple if the list type-arg is assignable
- // from all of the tuple type-args.
+ // We can only assign LIST = TUPLE if the LIST type-arg is assignable
+ // from all of the TUPLE type-args.
const Type &lhs = m_arguments[0];
for (size_t i = 0; i < other.m_arguments.size(); i++) {
const Type &rhs = other.m_arguments[i];
@@ -185,8 +200,8 @@
}
// If the number of type-args don't match, it can't be assignable.
if (m_arguments.size() != other.m_arguments.size()) {
- // Special case: a tuple can be initialized from a literal that is
- // a strict prefix of the tuple's type.
+ // Special case: a TUPLE can be initialized from a literal that is
+ // a strict prefix of the TUPLE's type.
if (m_primitive == TUPLE && other.m_primitive == TUPLE
&& m_arguments.size() > other.m_arguments.size()
&& other.is_literal()) {
@@ -219,36 +234,6 @@
{
return is_assignable_from(other, IGNORE_CONST);
}
-
-void
-Type::sanity_check() const
-{
- // Type::add_argument checks that a type does not end up with too many
- // type-args before adding them. We need to check that it got enough.
- switch (m_primitive) {
- case BOOL:
- case FLDFMT:
- case FUNC:
- case INT:
- case STRING:
- case VAR:
- break;
- case LIST:
- if (m_arguments.size() == 0) {
- throw Type::ArgumentError(sprintfxx(
- "type '%s' requires exactly one argument",
- Type::primitive_to_string(Type::LIST)));
- }
- break;
- case TUPLE:
- if (m_arguments.size() == 0) {
- throw Type::ArgumentError(sprintfxx(
- "type '%s' requires at least one argument",
- Type::primitive_to_string(Type::TUPLE)));
- }
- break;
- }
-}
} // namespace language
} // namespace pp
=======================================
--- /trunk/language/type.h Fri Jul 2 11:05:20 2010
+++ /trunk/language/type.h Fri Jul 2 17:29:57 2010
@@ -156,12 +156,6 @@
{
return m_arguments[index];
}
-
- // Make sure that compound types are properly defined (e.g. list has
- // an argument). Throws a specific Type::Error (e.g. ArgumentError)
- // on failure.
- void
- sanity_check() const;
private:
// This is used for internal type comparisons without regard to const
=======================================
--- /trunk/language/variable.cpp Thu Jun 24 07:46:16 2010
+++ /trunk/language/variable.cpp Fri Jul 2 17:29:57 2010
@@ -8,7 +8,6 @@
Variable::Datum::Datum(const Type &type) : m_type(type),
m_type_locked(true)
{
- type.sanity_check();
switch (m_type.primitive()) {
case Type::BOOL:
m_bool_value = false;